Skip to content

Instantly share code, notes, and snippets.

@Soul-Master
Last active April 23, 2019 06:13
Show Gist options
  • Save Soul-Master/3f07c010bfefab2af73409bce51bef1a to your computer and use it in GitHub Desktop.
Save Soul-Master/3f07c010bfefab2af73409bce51bef1a to your computer and use it in GitHub Desktop.
Demo Code from What's New in TypeScript (BRK2150) at Microsoft Build 2018
export type TypeFromConstructor<T> =
T extends StringConstructor ? string :
T extends NumberConstructor ? number :
any;
export type MethodDefinition = {
[x: string]: StringConstructor | NumberConstructor;
};
export type ServiceDefinition = {
[x: string]: MethodDefinition
};
export type ServiceMethod<T extends MethodDefinition> =
{} extends T ? () => boolean : (payload: RequestPayload<T>) => boolean;
export type ServiceObject<T extends ServiceDefinition> = {
[P in keyof T]: ServiceMethod<T[P]>
};
export type RequestPayload<T extends MethodDefinition> =
{} extends T ? undefined : { [P in keyof T]: TypeFromConstructor<T[P]> };
export type RequestHandler<T extends ServiceDefinition> =
(req: RequestObject<T>) => boolean;
export type RequestObject<T extends ServiceDefinition> = {
[P in keyof T]: { message: P, payload: RequestPayload<T[P]> }
}[keyof T];
export function createService<S extends ServiceDefinition>(serviceDef: S, handler: RequestHandler<S>): ServiceObject<S> {
const service = {} as any;
for (const name in serviceDef) {
service[name] = (payload: any) => handler({ message: name, payload });
}
return service as ServiceObject<S>;
}
import { createService } from './dynamicService';
const serviceDefinition = {
open: { filename: String },
insert: { pos: Number, text: String },
delete: { pos: Number, len: Number },
close: {}
};
const service = createService(serviceDefinition, req => {
switch (req.message) {
case 'open':
console.log('filename: ' + req.payload.filename);
break;
case 'insert':
console.log('pos: ' + req.payload.pos);
console.log('text: ' + req.payload.text);
break;
case 'delete':
console.log('pos: ' + req.payload.pos);
console.log('len: ' + req.payload.len);
break;
case 'close':
// This should be undefined.
console.log('payload: ' + req.payload);
break;
}
return true;
});
service.open({ filename: 'test.txt' });
service.insert({ pos: 0, text: 'hello world' });
service.delete({ pos: 0, len: 5 });
service.close();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment