Skip to content

Instantly share code, notes, and snippets.

@AJamesPhillips
Created May 22, 2021 12:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AJamesPhillips/0b0dc11ba67cf5ef63c8aadbdba41cb3 to your computer and use it in GitHub Desktop.
Save AJamesPhillips/0b0dc11ba67cf5ef63c8aadbdba41cb3 to your computer and use it in GitHub Desktop.
Type safe typescript PubSub
// try it out in the playground: https://www.typescriptlang.org/play?#code/LAKFoeggCAHBXARgfQM5OQMwIYGMAuA9gE4CeAdPquCJvAHYECWh9cG6KOBJp0APAFtssaAFMAHvjH0AJqmgB5RACsxBAHzQAFAEpQAb1DQT0XK1T5o2ADY20SVLmJNEY4qgBc0A9ADaANLQTGwA1mKkhJjQwrAAugD83tragmKoqNgA5mLesYFxutAAvFoAboRMsrp+cdAAviU+9TTGpnSM+CxsCIgCQZLScgrhkdGxWtpEsEy43gEANDHpmTl5IgX6IKY+bTsm5vSWMdikbg6ITi5uHsmpK9m5J7CbJeWV1bXQAD7QDLJiTAhMSyJq2eycK6udyoPzTWZxPb7Q7HSHOaEeJrCM5iC5Qm4KYpEv5yQHA0EJfx1dY4vHogk0famNHXGHkTAkACieAAFtoWRi3kidkZtkz9qgxPgACpMNKEeD4FJFUrQAU3e4ZR66JYABi24oaBtMLTAZp2HWYrDVSH64ikMnk0FGUWek3hc2gixtl3p7mSaS1a2er1VFSqxpMosNKKs2PO6phd0Dqye+QChTe0HDnzqv3+ZPoILBdjprI8cMIM1wiLFTNjPvxMKxpwTjj9mKJxRJAKBRYpVOgNLbvvL1HN4sTHnICFQfKnW2FpnBZYxsI9dW7U-HS5MxCl8GIbAYiaweCIZCmVdmSwXSNNjPaDCtx6O7dZZ54ZDtg0dIwiroTDoHrzLe74YgGDzBummZhh8ka7HW+z7vgh5sHoQpISKu7IhYcatri27JlBaYbBmKrvBGXz5qSfbFt2K7bpW1a1oaOwNtuLa0pxXY9oWxaUl8w6EeBDITmxZh4dARYAO6rgSTTbuyTA2NIxD8lmCgAITEneWHioxokwsxCJNLJ8kwjhpo7A+4nQChaE+OwiBgX0pq2Y+kAwNg9CEPgPLuFgKliJQO4gCEancGI0AAMI+WU2CoAAsqgWRJSIhhIrg8WJcgsgKogNi4vgIjeL4EjePQ8CCDcDRZTlqDIC4WQ8vgyC4DYsyhGV0CkJV1W1e5NANtl9AJY1vQXE0k2cJ+F6kPwcVjYlKVpSIGh6MNDXIDNSDkJw2gAESjeNeUFUVyAlbAh1LKkqU9RV0kDe4RqYdGpgooQRXkDYhBZEdWR+dA+VIEV0BXTdMSpeQEhbPUWwnblu2IPtSBHYjjXNa17WdbgoSQ3dWQ9X1T01S98NvVlFhfSFv3-YdgNWFjVgdV1kOCNDpBw4uIAYztHB7b06PbSDhXFSIkPld4ACMRqgHzyMzmjx3bczONs0svgk7L8M0EAA
// pub_sub_factory.ts
export function pub_sub_factory <map extends Object> ()
{
const all_subscribers: { [K in keyof map]?: ((message: map[K]) => void)[] } = {}
function pub <K extends keyof map> (topic: K, message: map[K])
{
const maybe_subscribers: ((message: map[K]) => void)[] | undefined = all_subscribers[topic]
const subscribers = maybe_subscribers === undefined ? [] : maybe_subscribers
subscribers.forEach(subscriber =>
{
setTimeout(() => subscriber(message), 0)
})
}
function sub <K extends keyof map> (topic: K, subscriber: (message: map[K]) => void)
{
const maybe_subscribers: ((message: map[K]) => void)[] | undefined = all_subscribers[topic]
const subscribers = maybe_subscribers === undefined ? [] : maybe_subscribers
subscribers.push(subscriber)
all_subscribers[topic] = subscribers
return unsubscribe_factory(topic, subscriber)
}
function unsubscribe_factory <K extends keyof map> (topic: K, subscriber: (message: map[K]) => void)
{
return () =>
{
const maybe_subscribers: ((message: map[K]) => void)[] | undefined = all_subscribers[topic]
const subscribers = maybe_subscribers === undefined ? [] : maybe_subscribers
const new_subscribers = subscribers.filter(s => s !== subscriber)
all_subscribers[topic] = new_subscribers
}
}
return { pub, sub }
}
// another_file.ts
interface CanvasMsgMap
{
canvas_double_tap: { x: number }
canvas_right_click: { y: number }
}
export const canvas_pub_sub = pub_sub_factory<CanvasMsgMap>()
canvas_pub_sub.sub("canvas_double_tap", (msg: { x: number }) =>
{
console.log("got double tap", msg.x)
})
canvas_pub_sub.sub("canvas_right_click", (msg: { y: number }) =>
{
console.log("got right click", msg.y)
})
canvas_pub_sub.pub("canvas_double_tap", { x: 1 })
canvas_pub_sub.pub("canvas_right_click", { y: 1 })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment