let's continue convert unity game into phaser 3 typescript game. convert this script, show complete typescript version:

// Messenger
using System;
using System.Collections.Generic;
using UnityEngine;

internal static class Messenger
{
	public class BroadcastException : Exception
	{
		public BroadcastException(string msg)
			: base(msg)
		{
		}
	}

	public class ListenerException : Exception
	{
		public ListenerException(string msg)
			: base(msg)
		{
		}
	}

	private static MessengerHelper messengerHelper = new GameObject("MessengerHelper").AddComponent<MessengerHelper>();

	public static Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();

	public static List<string> permanentMessages = new List<string>();

	public static void MarkAsPermanent(string eventType)
	{
		permanentMessages.Add(eventType);
	}

	public static void Cleanup()
	{
		List<string> list = new List<string>();
		foreach (KeyValuePair<string, Delegate> item in eventTable)
		{
			bool flag = false;
			foreach (string permanentMessage in permanentMessages)
			{
				if (item.Key == permanentMessage)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				list.Add(item.Key);
			}
		}
		foreach (string item2 in list)
		{
			eventTable.Remove(item2);
		}
	}

	public static void PrintEventTable()
	{
		Debug.Log("\t\t\t=== MESSENGER PrintEventTable ===");
		foreach (KeyValuePair<string, Delegate> item in eventTable)
		{
			Debug.Log("\t\t\t" + item.Key + "\t\t" + item.Value);
		}
		Debug.Log("\n");
	}

	public static void OnListenerAdding(string eventType, Delegate listenerBeingAdded)
	{
		if (!eventTable.ContainsKey(eventType))
		{
			eventTable.Add(eventType, null);
		}
		Delegate @delegate = eventTable[eventType];
		if ((object)@delegate != null && @delegate.GetType() != listenerBeingAdded.GetType())
		{
			throw new ListenerException($"Attempting to add listener with inconsistent signature for event type {eventType}. Current listeners have type {@delegate.GetType().Name} and listener being added has type {listenerBeingAdded.GetType().Name}");
		}
	}

	public static void OnListenerRemoving(string eventType, Delegate listenerBeingRemoved)
	{
		if (eventTable.ContainsKey(eventType))
		{
			Delegate @delegate = eventTable[eventType];
			if ((object)@delegate == null)
			{
				throw new ListenerException($"Attempting to remove listener with for event type \"{eventType}\" but current listener is null.");
			}
			if (@delegate.GetType() != listenerBeingRemoved.GetType())
			{
				throw new ListenerException($"Attempting to remove listener with inconsistent signature for event type {eventType}. Current listeners have type {@delegate.GetType().Name} and listener being removed has type {listenerBeingRemoved.GetType().Name}");
			}
			return;
		}
		throw new ListenerException($"Attempting to remove listener for type \"{eventType}\" but Messenger doesn't know about this event type.");
	}

	public static void OnListenerRemoved(string eventType)
	{
		if ((object)eventTable[eventType] == null)
		{
			eventTable.Remove(eventType);
		}
	}

	public static void OnBroadcasting(string eventType)
	{
		if (!eventTable.ContainsKey(eventType))
		{
			throw new BroadcastException($"Broadcasting message \"{eventType}\" but no listener found. Try marking the message with Messenger.MarkAsPermanent.");
		}
	}

	public static BroadcastException CreateBroadcastSignatureException(string eventType)
	{
		return new BroadcastException($"Broadcasting message \"{eventType}\" but listeners have a different signature than the broadcaster.");
	}

	public static void AddListener(string eventType, Callback handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (Callback)Delegate.Combine((Callback)eventTable[eventType], handler);
	}

	public static void AddListenerINT(string eventType, CallbackINT handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (CallbackINT)Delegate.Combine((CallbackINT)eventTable[eventType], handler);
	}

	public static void AddListenerSTRING(string eventType, CallbackSTRING handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (CallbackSTRING)Delegate.Combine((CallbackSTRING)eventTable[eventType], handler);
	}

	public static void CoAddListener(string eventType, CoCallback handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (CoCallback)Delegate.Combine((CoCallback)eventTable[eventType], handler);
	}

	public static void AddListener<T>(string eventType, Callback<T> handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (Callback<T>)Delegate.Combine((Callback<T>)eventTable[eventType], handler);
	}

	public static void CoAddListener<T>(string eventType, CoCallback<T> handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (CoCallback<T>)Delegate.Combine((CoCallback<T>)eventTable[eventType], handler);
	}

	public static void AddListenerINT<T>(string eventType, CallbackINT<T> handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (CallbackINT<T>)Delegate.Combine((CallbackINT<T>)eventTable[eventType], handler);
	}

	public static void AddListener<T, U>(string eventType, Callback<T, U> handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (Callback<T, U>)Delegate.Combine((Callback<T, U>)eventTable[eventType], handler);
	}

	public static void CoAddListener<T, U>(string eventType, CoCallback<T, U> handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (CoCallback<T, U>)Delegate.Combine((CoCallback<T, U>)eventTable[eventType], handler);
	}

	public static void AddListener<T, U, V>(string eventType, Callback<T, U, V> handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (Callback<T, U, V>)Delegate.Combine((Callback<T, U, V>)eventTable[eventType], handler);
	}

	public static void AddListener<T, U, V, S>(string eventType, Callback<T, U, V, S> handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (Callback<T, U, V, S>)Delegate.Combine((Callback<T, U, V, S>)eventTable[eventType], handler);
	}

	public static void CoAddListener<T, U, V>(string eventType, CoCallback<T, U, V> handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (CoCallback<T, U, V>)Delegate.Combine((CoCallback<T, U, V>)eventTable[eventType], handler);
	}

	public static void RemoveListener(string eventType, Callback handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (Callback)Delegate.Remove((Callback)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void RemoveListenerINT(string eventType, CallbackINT handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (CallbackINT)Delegate.Remove((CallbackINT)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void RemoveListenerSTRING(string eventType, CallbackSTRING handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (CallbackSTRING)Delegate.Remove((CallbackSTRING)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void CoRemoveListener(string eventType, CoCallback handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (CoCallback)Delegate.Remove((CoCallback)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void RemoveListener<T>(string eventType, Callback<T> handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (Callback<T>)Delegate.Remove((Callback<T>)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void CoRemoveListener<T>(string eventType, CoCallback<T> handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (CoCallback<T>)Delegate.Remove((CoCallback<T>)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void RemoveListener<T, U>(string eventType, Callback<T, U> handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (Callback<T, U>)Delegate.Remove((Callback<T, U>)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void CoRemoveListener<T, U>(string eventType, CoCallback<T, U> handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (CoCallback<T, U>)Delegate.Remove((CoCallback<T, U>)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void RemoveListener<T, U, V>(string eventType, Callback<T, U, V> handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (Callback<T, U, V>)Delegate.Remove((Callback<T, U, V>)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void CoRemoveListener<T, U, V>(string eventType, CoCallback<T, U, V> handler)
	{
		OnListenerRemoving(eventType, handler);
		eventTable[eventType] = (CoCallback<T, U, V>)Delegate.Remove((CoCallback<T, U, V>)eventTable[eventType], handler);
		OnListenerRemoved(eventType);
	}

	public static void RemoveListener<T, U, V, S>(string eventType, Callback<T, U, V, S> handler)
	{
		OnListenerAdding(eventType, handler);
		eventTable[eventType] = (Callback<T, U, V, S>)Delegate.Combine((Callback<T, U, V, S>)eventTable[eventType], handler);
	}

	public static void Broadcast(string eventType)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is Callback callback))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			callback();
		}
	}

	public static int BroadcastINT(string eventType)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (value is CallbackINT callbackINT)
			{
				return callbackINT();
			}
			throw CreateBroadcastSignatureException(eventType);
		}
		return -1;
	}

	public static string BroadcastSTRING(string eventType)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (value is CallbackSTRING callbackSTRING)
			{
				return callbackSTRING();
			}
			throw CreateBroadcastSignatureException(eventType);
		}
		return null;
	}

	public static void CoBroadcast(string eventType)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is CoCallback coCallback))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			messengerCoHandler.use.StartCoroutine(coCallback());
		}
	}

	public static void Broadcast<T>(string eventType, T arg1)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is Callback<T> callback))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			callback(arg1);
		}
	}

	public static void BroadcastINT<T>(string eventType, T arg1)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is CallbackINT<T> callbackINT))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			callbackINT(arg1);
		}
	}

	public static void CoBroadcast<T>(string eventType, T arg1)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is CoCallback<T> coCallback))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			messengerCoHandler.use.StartCoroutine(coCallback(arg1));
		}
	}

	public static void Broadcast<T, U>(string eventType, T arg1, U arg2)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is Callback<T, U> callback))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			callback(arg1, arg2);
		}
	}

	public static void CoBroadcast<T, U>(string eventType, T arg1, U arg2)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is CoCallback<T, U> coCallback))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			messengerCoHandler.use.StartCoroutine(coCallback(arg1, arg2));
		}
	}

	public static void Broadcast<T, U, V>(string eventType, T arg1, U arg2, V arg3)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is Callback<T, U, V> callback))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			callback(arg1, arg2, arg3);
		}
	}

	public static void CoBroadcast<T, U, V>(string eventType, T arg1, U arg2, V arg3)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is CoCallback<T, U, V> coCallback))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			messengerCoHandler.use.StartCoroutine(coCallback(arg1, arg2, arg3));
		}
	}

	public static void Broadcast<T, U, V, S>(string eventType, T arg1, U arg2, V arg3, S arg4)
	{
		OnBroadcasting(eventType);
		if (eventTable.TryGetValue(eventType, out var value))
		{
			if (!(value is Callback<T, U, V, S> callback))
			{
				throw CreateBroadcastSignatureException(eventType);
			}
			callback(arg1, arg2, arg3, arg4);
		}
	}
}