Skip to content
This repository has been archived by the owner on Dec 12, 2020. It is now read-only.

Commit

Permalink
fix: Create generic type with custom name (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
ktutnik committed Jun 6, 2020
1 parent f48ab94 commit c3dceee
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 23 deletions.
10 changes: 4 additions & 6 deletions src/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export function ignore() {
return decorate(<PrivateDecorator>{ [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) => <TypeDecorator>{ [DecoratorId]: symOverride, kind: "Override", type, genericParams, target }, ["Parameter", "Method", "Property"], { inherit: false, allowMultiple: false })
}
Expand Down Expand Up @@ -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<T extends Class>(parent: T, ...params: TypeOverride[]) {
const Type = (() => {
class DynamicType extends parent { }
return DynamicType as T;
})();
export function create<T extends Class>(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
}
Expand Down
4 changes: 4 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ function useCache<K, P extends any[], R>(cache: Map<K, R>, 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
}
Expand Down
9 changes: 8 additions & 1 deletion src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
30 changes: 15 additions & 15 deletions test/__snapshots__/generic.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ Object {
"decorators": Array [
Object {
"kind": "GenericType",
"target": DynamicType,
"target": SuperClass,
"types": Array [
Number,
String,
Expand Down Expand Up @@ -411,10 +411,10 @@ Object {
"typeClassification": "Primitive",
},
],
"name": "DynamicType",
"name": "SuperClass",
"properties": Array [],
"super": SuperClass,
"type": DynamicType,
"type": SuperClass,
"typeClassification": "Class",
}
`;
Expand Down Expand Up @@ -964,7 +964,7 @@ Object {
"decorators": Array [
Object {
"kind": "GenericType",
"target": DynamicType,
"target": CustomGeneric,
"types": Array [
String,
],
Expand All @@ -977,7 +977,7 @@ Object {
],
"kind": "Class",
"methods": Array [],
"name": "DynamicType",
"name": "CustomGeneric",
"properties": Array [
Object {
"decorators": Array [],
Expand All @@ -990,7 +990,7 @@ Object {
},
],
"super": CustomGeneric,
"type": DynamicType,
"type": CustomGeneric,
"typeClassification": "Class",
}
`;
Expand All @@ -1005,7 +1005,7 @@ Object {
"decorators": Array [
Object {
"kind": "GenericType",
"target": DynamicType,
"target": CustomGeneric,
"types": Array [
String,
],
Expand All @@ -1018,7 +1018,7 @@ Object {
],
"kind": "Class",
"methods": Array [],
"name": "DynamicType",
"name": "CustomGeneric",
"properties": Array [
Object {
"decorators": Array [],
Expand All @@ -1031,7 +1031,7 @@ Object {
},
],
"super": CustomGeneric,
"type": DynamicType,
"type": CustomGeneric,
"typeClassification": "Class",
}
`;
Expand All @@ -1046,7 +1046,7 @@ Object {
"decorators": Array [
Object {
"kind": "GenericType",
"target": DynamicType,
"target": CustomGeneric,
"types": Array [
String,
],
Expand All @@ -1059,7 +1059,7 @@ Object {
],
"kind": "Class",
"methods": Array [],
"name": "DynamicType",
"name": "CustomGeneric",
"properties": Array [
Object {
"decorators": Array [],
Expand All @@ -1072,7 +1072,7 @@ Object {
},
],
"super": CustomGeneric,
"type": DynamicType,
"type": CustomGeneric,
"typeClassification": "Class",
}
`;
Expand All @@ -1087,7 +1087,7 @@ Object {
"decorators": Array [
Object {
"kind": "GenericType",
"target": DynamicType,
"target": CustomGeneric,
"types": Array [
String,
],
Expand All @@ -1100,7 +1100,7 @@ Object {
],
"kind": "Class",
"methods": Array [],
"name": "DynamicType",
"name": "CustomGeneric",
"properties": Array [
Object {
"decorators": Array [],
Expand All @@ -1113,7 +1113,7 @@ Object {
},
],
"super": CustomGeneric,
"type": DynamicType,
"type": CustomGeneric,
"typeClassification": "Class",
}
`;
1 change: 1 addition & 0 deletions test/__snapshots__/index.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Object {
"ignore": ignore,
"mergeDecorator": mergeDecorator,
"metadata": Object {
"createClass": createClass,
"getMethods": getMethods,
"getProperties": getProperties,
"isCallback": isCallback,
Expand Down
10 changes: 9 additions & 1 deletion test/generic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,14 +312,22 @@ describe("Create Generic", () => {
expect(instance).toBeInstanceOf(SuperClass)
expect(instance).toBeInstanceOf(ChildClass)
})
it("Should able to change class name", () => {
@generic.template("T")
class SuperClass<T> {
@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<T, U> {
@type("T")
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", () => {
Expand Down

0 comments on commit c3dceee

Please sign in to comment.