Skip to content

Instantly share code, notes, and snippets.

@NickStrupat
Last active May 21, 2019 22:13
Show Gist options
  • Save NickStrupat/afd8bf4934fd6c2991fd5df3801ce435 to your computer and use it in GitHub Desktop.
Save NickStrupat/afd8bf4934fd6c2991fd5df3801ce435 to your computer and use it in GitHub Desktop.
import { strict as assert } from 'assert';
/**
* This class supports retrieving a class type name at run-time. It requires TypeScript decorators.
* Usage: Register the typename with `@TypeName.decorate(...)`
*
* @TypeName.decorate("Foo")
* class Foo {
* readonly text: string = "text";
* }
*
* const typeName = TypeName.tryGet(new Foo());
* assert(typeName === "Foo")
*
* class Bar {}
* const typeName = TypeName.tryGet(new Bar());
* assert(typeName === undefined)
*
*/
class TypeName {
private constructor() {}
private static readonly typeNameSymbol = Symbol("typeName");
public static decorate(name: string): Function {
return function getExtendedContructor<Base extends { new(...args: any[]): any }>(target: Base) {
return class Constructor extends target {
constructor(...args: any[]) {
super(...args);
(this as any)[TypeName.typeNameSymbol] = name;
}
}
}
}
public static tryGet(o: any): string | undefined {
if (o === undefined || o === null || typeof o[TypeName.typeNameSymbol] !== typeof "")
return undefined;
return o[TypeName.typeNameSymbol];
}
}
function arraysEqual(array1: Array<unknown>, array2: Array<unknown>) {
return array1 && array2 && array1.length === array2.length && array1.every((v, i) => v === array2[i]);
}
@TypeName.decorate("Foo")
class Foo {
readonly text: string = "text";
public static readonly staticText = "staticText";
}
const foo = new Foo();
assert(TypeName.tryGet(foo) === "Foo");
assert(arraysEqual(Object.getOwnPropertyNames(foo), ["text"]));
assert(arraysEqual(Object.keys(foo), ["text"]));
assert(arraysEqual(Object.getOwnPropertySymbols(foo), [(<any>TypeName).typeNameSymbol]));
assert(typeof Foo.staticText === typeof "");
class Bar {
readonly count: number = 0;
public static readonly staticCount = 0;
}
const bar = new Bar();
assert(TypeName.tryGet(bar) === undefined);
assert(arraysEqual(Object.getOwnPropertyNames(bar), ["count"]));
assert(arraysEqual(Object.keys(bar), ["count"]));
assert(arraysEqual(Object.getOwnPropertySymbols(bar), []));
assert(typeof Bar.staticCount === typeof 0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment