diff --git a/src/decorators.ts b/src/decorators.ts index ef11363..7e46456 100644 --- a/src/decorators.ts +++ b/src/decorators.ts @@ -131,7 +131,7 @@ export function ignore() { return decorate({ [DecoratorId]: symIgnore, kind: "Ignore" }, ["Parameter", "Method", "Property"], { allowMultiple: false }) } -export function type(type: TypeOverride | ((x: any) => TypeOverride), ...genericParams:(string|string[])[]) { +export function type(type: TypeOverride | ((x: any) => TypeOverride), ...genericParams: (string | string[])[]) { // type is not inheritable because derived class can define their own type override return decorate((target: any) => { [DecoratorId]: symOverride, kind: "Override", type, genericParams, target }, ["Parameter", "Method", "Property"], { inherit: false, allowMultiple: false }) } @@ -159,11 +159,9 @@ export namespace generic { * @param parent Super class that the class inherited from * @param params List of generic type parameters */ - export function create(parent: T, ...params: TypeOverride[]) { - const Type = (() => { - class DynamicType extends parent { } - return DynamicType as T; - })(); + export function create(parent: T | { parent: T, name: string }, ...params: TypeOverride[]) { + const opt = (typeof parent === "object") ? parent : { parent: parent, name: parent.name } + const Type = metadata.createClass(opt.parent, opt.name) Reflect.decorate([generic.type(...params)], Type) return Type } diff --git a/src/helpers.ts b/src/helpers.ts index b5f4c97..d48bc0e 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -20,6 +20,10 @@ function useCache(cache: Map, fn: (...args: P) => R } namespace metadata { + export function createClass(parent: Class, name: string): Class { + return { [name]: class extends parent { } }[name]; + } + export function isParameterProperties(meta: any): meta is ParameterPropertyReflection { return meta && meta.kind === "Property" && (meta as ParameterPropertyReflection).isParameter } diff --git a/src/parser.ts b/src/parser.ts index 4b75adf..25564c3 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -50,7 +50,14 @@ function getNamesFromAst(nodes: any[]) { } function getCode(fn:Class|Function){ - return fn.toString().replace("[native code]", "") + const code = fn.toString() + if(code === "class extends parent {}") { + const token = code.split(" ") + token.splice(1, 0, "DynamicClass") + return token.join(" ") + } + else + return code.replace("[native code]", "") } function getMethodParameters(fn: Class, method: string) { diff --git a/test/__snapshots__/generic.spec.js.snap b/test/__snapshots__/generic.spec.js.snap index d024520..af11253 100644 --- a/test/__snapshots__/generic.spec.js.snap +++ b/test/__snapshots__/generic.spec.js.snap @@ -378,7 +378,7 @@ Object { "decorators": Array [ Object { "kind": "GenericType", - "target": DynamicType, + "target": SuperClass, "types": Array [ Number, String, @@ -411,10 +411,10 @@ Object { "typeClassification": "Primitive", }, ], - "name": "DynamicType", + "name": "SuperClass", "properties": Array [], "super": SuperClass, - "type": DynamicType, + "type": SuperClass, "typeClassification": "Class", } `; @@ -964,7 +964,7 @@ Object { "decorators": Array [ Object { "kind": "GenericType", - "target": DynamicType, + "target": CustomGeneric, "types": Array [ String, ], @@ -977,7 +977,7 @@ Object { ], "kind": "Class", "methods": Array [], - "name": "DynamicType", + "name": "CustomGeneric", "properties": Array [ Object { "decorators": Array [], @@ -990,7 +990,7 @@ Object { }, ], "super": CustomGeneric, - "type": DynamicType, + "type": CustomGeneric, "typeClassification": "Class", } `; @@ -1005,7 +1005,7 @@ Object { "decorators": Array [ Object { "kind": "GenericType", - "target": DynamicType, + "target": CustomGeneric, "types": Array [ String, ], @@ -1018,7 +1018,7 @@ Object { ], "kind": "Class", "methods": Array [], - "name": "DynamicType", + "name": "CustomGeneric", "properties": Array [ Object { "decorators": Array [], @@ -1031,7 +1031,7 @@ Object { }, ], "super": CustomGeneric, - "type": DynamicType, + "type": CustomGeneric, "typeClassification": "Class", } `; @@ -1046,7 +1046,7 @@ Object { "decorators": Array [ Object { "kind": "GenericType", - "target": DynamicType, + "target": CustomGeneric, "types": Array [ String, ], @@ -1059,7 +1059,7 @@ Object { ], "kind": "Class", "methods": Array [], - "name": "DynamicType", + "name": "CustomGeneric", "properties": Array [ Object { "decorators": Array [], @@ -1072,7 +1072,7 @@ Object { }, ], "super": CustomGeneric, - "type": DynamicType, + "type": CustomGeneric, "typeClassification": "Class", } `; @@ -1087,7 +1087,7 @@ Object { "decorators": Array [ Object { "kind": "GenericType", - "target": DynamicType, + "target": CustomGeneric, "types": Array [ String, ], @@ -1100,7 +1100,7 @@ Object { ], "kind": "Class", "methods": Array [], - "name": "DynamicType", + "name": "CustomGeneric", "properties": Array [ Object { "decorators": Array [], @@ -1113,7 +1113,7 @@ Object { }, ], "super": CustomGeneric, - "type": DynamicType, + "type": CustomGeneric, "typeClassification": "Class", } `; diff --git a/test/__snapshots__/index.spec.js.snap b/test/__snapshots__/index.spec.js.snap index 6fefcf8..d797b59 100644 --- a/test/__snapshots__/index.spec.js.snap +++ b/test/__snapshots__/index.spec.js.snap @@ -22,6 +22,7 @@ Object { "ignore": ignore, "mergeDecorator": mergeDecorator, "metadata": Object { + "createClass": createClass, "getMethods": getMethods, "getProperties": getProperties, "isCallback": isCallback, diff --git a/test/generic.spec.ts b/test/generic.spec.ts index 9d22360..a85bd95 100644 --- a/test/generic.spec.ts +++ b/test/generic.spec.ts @@ -312,6 +312,15 @@ describe("Create Generic", () => { expect(instance).toBeInstanceOf(SuperClass) expect(instance).toBeInstanceOf(ChildClass) }) + it("Should able to change class name", () => { + @generic.template("T") + class SuperClass { + @type("T") + method(): T { return {} as any } + } + const ChildClass = generic.create({ parent: SuperClass, name: "MyDynamicClass" }, Number) + expect(ChildClass.name).toBe("MyDynamicClass") + }) it("Should add reflection properly", () => { @generic.template("T", "U") class SuperClass { @@ -319,7 +328,6 @@ describe("Create Generic", () => { method(@type("U") par: U): T { return {} as any } } const ChildClass = generic.create(SuperClass, Number, String) - const instance = new ChildClass() expect(reflect(ChildClass)).toMatchSnapshot() }) it("Should able to create multiple time", () => {