Last active
May 10, 2017 12:17
-
-
Save despairblue/571a393d829cc43698f5701217d6c991 to your computer and use it in GitHub Desktop.
typesafe queue consumer
This file contains 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
/** | |
* Types | |
*/ | |
export interface I0 { | |
namespace: Namespaces | |
} | |
export interface IA extends I0 { | |
namespace: 'A' | |
} | |
export interface IB extends I0 { | |
namespace: 'B' | |
} | |
export interface IC extends I0 { | |
namespace: 'C' | |
payload: string | |
} | |
export interface ID extends I0 { | |
namespace: 'D' | |
} | |
export type Messages = IA | IB | IC | ID | |
export type Namespaces = Messages['namespace'] | |
class NamespaceClass { | |
constructor( | |
public A = null, | |
public B = null, | |
public C = null, | |
public D = null, | |
) {} | |
} | |
export const namespaces = Object.keys(new NamespaceClass()) as NamespacesClassNamespaces[] | |
// If either of these does not typecheck you forgot to add your namespace to the | |
// `NamespaceClass` or the `Messages` union type. | |
// | |
// Both are necessary for different reasons: | |
// | |
// The Class can be used to get an Array of all keys and thus get an Array of | |
// all namespaces which is used by the mail-service to query the queue. | |
// Forgetting a namespace there would lead to the mail-service never getting | |
// those messages from the queue. | |
// | |
// The union type is used for exhaustiveness checking in the mail-service. If | |
// the union type contains a type that is not handled by the mail-service the | |
// compiler will yell. This makes sure that for all messages the mail-service | |
// queries the queue for, corresponding code exists that handles those messages. | |
type NamespacesClassNamespaces = keyof NamespaceClass | |
// If this fails: add the missing interface to the `Messages` union type. | |
let selfCheck1: Namespaces[] | |
selfCheck1 = namespaces as NamespacesClassNamespaces[] | |
// If this fails: add the missing namespace as a property to the | |
// `NamespaceClass`. | |
let selfCheck2: NamespacesClassNamespaces[] | |
selfCheck2 = namespaces as Namespaces[] | |
/** | |
* Dummy Implementation | |
*/ | |
// tslint:disable-next-line: max-classes-per-file | |
class DummyQueue { | |
public find(_: string[]): Messages { | |
return {} as Messages | |
} | |
} | |
const dummyQueue = new DummyQueue() | |
while (true) { | |
handleMessage(getMessage(dummyQueue)) | |
} | |
function getMessage(queue: DummyQueue): Messages { | |
return queue.find(namespaces) | |
} | |
function handleMessage(message: Messages): string { | |
switch (message.namespace) { | |
case 'A': | |
return message.namespace | |
case 'B': | |
return message.namespace | |
case 'C': | |
return message.payload | |
case 'D': | |
return message.namespace | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment