From d8dbfbf446799252316c3a1697aa88f528bee11b Mon Sep 17 00:00:00 2001 From: Codeco Date: Sun, 6 Oct 2019 21:19:19 -0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8Add=20support=20to=20TSImportType?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/metadata/serializeType.ts | 33 ++++++++++++++++++++++ test/__fixtures__/nest-injection/code.js | 3 ++ test/__fixtures__/nest-injection/output.js | 13 +++++++-- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/metadata/serializeType.ts b/src/metadata/serializeType.ts index a60cc0e..e7b35cc 100644 --- a/src/metadata/serializeType.ts +++ b/src/metadata/serializeType.ts @@ -84,6 +84,36 @@ function serializeTypeReferenceNode( ); } +function serializeTypeImportNode( + className: string, + node: t.TSImportType +) { + /** + * We need to save references to this type since it is going + * to be used as a Value (and not just as a Type) here. + * + * This is resolved in main plugin method, calling + * `path.scope.crawl()` which updates the bindings. + */ + const reference = serializeReference(node.qualifier!); + + /** + * We don't know if type is just a type (interface, etc.) or a concrete + * value (class, etc.). + * `typeof` operator allows us to use the expression even if it is not + * defined, fallback is just `Object`. + */ + return t.conditionalExpression( + t.binaryExpression( + '===', + t.unaryExpression('typeof', reference), + t.stringLiteral('undefined') + ), + t.identifier('Object'), + t.clone(reference) + ); +} + /** * Checks if node (this should be the result of `serializeReference`) member * expression or identifier is a reference to self (class name). @@ -193,6 +223,9 @@ function serializeTypeNode(className: string, node: t.TSType): SerializedType { case 'TSConditionalType': return serializeTypeList(className, [node.trueType, node.falseType]); + case 'TSImportType': + return serializeTypeImportNode(className, node); + case 'TSTypeQuery': case 'TSTypeOperator': case 'TSIndexedAccessType': diff --git a/test/__fixtures__/nest-injection/code.js b/test/__fixtures__/nest-injection/code.js index 9a476ff..7afe45a 100644 --- a/test/__fixtures__/nest-injection/code.js +++ b/test/__fixtures__/nest-injection/code.js @@ -10,6 +10,9 @@ export class AppController { @Inject() private appService2: AppService; + @Inject() + private appService3: import('./app.service').AppService; + @Get() getHello(): string { return this.appService.getHello(); diff --git a/test/__fixtures__/nest-injection/output.js b/test/__fixtures__/nest-injection/output.js index 303a92a..b5996a4 100644 --- a/test/__fixtures__/nest-injection/output.js +++ b/test/__fixtures__/nest-injection/output.js @@ -1,4 +1,4 @@ -var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _class, _class2, _descriptor, _descriptor2, _temp; +var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _dec10, _class, _class2, _descriptor, _descriptor2, _descriptor3, _temp; function _initializerDefineProperty(target, property, descriptor, context) { if (!descriptor) return; Object.defineProperty(target, property, { enumerable: descriptor.enumerable, configurable: descriptor.configurable, writable: descriptor.writable, value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); } @@ -7,13 +7,15 @@ function _applyDecoratedDescriptor(target, property, decorators, descriptor, con function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and set to use loose mode. ' + 'To use proposal-class-properties in spec mode with decorators, wait for ' + 'the next major version of decorators in stage 2.'); } import { AppService } from './app.service'; -export let AppController = (_dec = Controller(), _dec2 = Reflect.metadata("design:paramtypes", [typeof AppService === "undefined" ? Object : AppService]), _dec3 = Inject(), _dec4 = Reflect.metadata("design:type", typeof AppService === "undefined" ? Object : AppService), _dec5 = Inject(), _dec6 = Reflect.metadata("design:type", typeof AppService === "undefined" ? Object : AppService), _dec7 = Get(), _dec8 = Reflect.metadata("design:paramtypes", []), _dec(_class = _dec2(_class = (_class2 = (_temp = class AppController { +export let AppController = (_dec = Controller(), _dec2 = Reflect.metadata("design:paramtypes", [typeof AppService === "undefined" ? Object : AppService]), _dec3 = Inject(), _dec4 = Reflect.metadata("design:type", typeof AppService === "undefined" ? Object : AppService), _dec5 = Inject(), _dec6 = Reflect.metadata("design:type", typeof AppService === "undefined" ? Object : AppService), _dec7 = Inject(), _dec8 = Reflect.metadata("design:type", typeof AppService === "undefined" ? Object : AppService), _dec9 = Get(), _dec10 = Reflect.metadata("design:paramtypes", []), _dec(_class = _dec2(_class = (_class2 = (_temp = class AppController { constructor(appService) { this.appService = appService; _initializerDefineProperty(this, "appService", _descriptor, this); _initializerDefineProperty(this, "appService2", _descriptor2, this); + + _initializerDefineProperty(this, "appService3", _descriptor3, this); } getHello() { @@ -30,4 +32,9 @@ export let AppController = (_dec = Controller(), _dec2 = Reflect.metadata("desig enumerable: true, writable: true, initializer: null -}), _applyDecoratedDescriptor(_class2.prototype, "getHello", [_dec7, _dec8], Object.getOwnPropertyDescriptor(_class2.prototype, "getHello"), _class2.prototype)), _class2)) || _class) || _class); +}), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, "appService3", [_dec7, _dec8], { + configurable: true, + enumerable: true, + writable: true, + initializer: null +}), _applyDecoratedDescriptor(_class2.prototype, "getHello", [_dec9, _dec10], Object.getOwnPropertyDescriptor(_class2.prototype, "getHello"), _class2.prototype)), _class2)) || _class) || _class);