Created
May 22, 2021 12:51
-
-
Save AJamesPhillips/0b0dc11ba67cf5ef63c8aadbdba41cb3 to your computer and use it in GitHub Desktop.
Type safe typescript PubSub
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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