Last active
May 21, 2019 22:13
-
-
Save NickStrupat/afd8bf4934fd6c2991fd5df3801ce435 to your computer and use it in GitHub Desktop.
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
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