TypeScript [Bug] Mixin参数未能作为内部类的方法参数类型使用

3zwtqj6y  于 4个月前  发布在  TypeScript
关注(0)|答案(8)|浏览(51)

🔎 搜索词

mixin, 参数, 类方法, 类型声明, 装饰器

🕗 版本与回归信息

  • 这会导致崩溃
  • 在所有我尝试过的版本中,我都遇到了这个问题,我也查看了关于 mixin & parameter 的常见问题解答条目

⏯ Playground链接

带有相关代码的Playground链接

💻 代码

const register: MethodDecorator = () => { }

const validate: ParameterDecorator = () => { }

function mixin<T>(Model: new (...data: any[]) => T) {
    class Trait {
        @register
        method(@validate input: Model) { }
    }
    return Trait;
}

class TestModel {
    id = 0
}

class TestController extends mixin(TestModel) { }

🙁 实际行为

类型检查导致崩溃

error TS2749: 'Model' refers to a value, but is being used as a type here. Did you mean 'typeof Model'?

         method(@validate input: Model) {
                                 ~~~~~

编译似乎可以正常工作

function mixin(Model) {
    var _a;
    class Trait {
        method(input) { }
    }
    __decorate([
        register,
        __param(0, validate),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_a = typeof Model !== "undefined" && Model) === "function" ? _a : Object]),
        __metadata("design:returntype", void 0)
    ], Trait.prototype, "method", null);
    return Trait;
}

🙂 预期行为

显示的示例代码可以正常工作,因此使用装饰器框架的项目会变得简单很多,就像我的服务脚手架所做的那样: idea2app/REST-Node-ts#1

ewm0tg9j

ewm0tg9j1#

错误信息是正确的。Model 指的是函数参数的值,你应该使用 typeof 来指代它的类型。请参阅 https://www.typescriptlang.org/docs/handbook/2/typeof-types.html

6tqwzwtp

6tqwzwtp2#

错误信息是正确的。Model 指的是函数参数的值,你应该使用 typeof 来指代它的类型。参见 https://www.typescriptlang.org/docs/handbook/2/typeof-types.html
我知道 typeof 是“正确的语法”,但如果我按照那样修改,Parameter Decorator 将无法获取发出的类:

const register: MethodDecorator = () => { }

const validate: ParameterDecorator = () => { }

function mixin<T>(Model: new (...data: any[]) => T) {
    class Trait {
        @register
-        method(@validate input: Model) { }
+        method(@validate input: typeof Model) { }
    }
    return Trait;
}

class TestModel {
    id = 0
}

class TestController extends mixin(TestModel) { }
function mixin(Model) {
    var _a;
    class Trait {
        method(input) { }
    }
    __decorate([
        register,
        __param(0, validate),
        __metadata("design:type", Function),
-        __metadata("design:paramtypes", [typeof (_a = typeof Model !== "undefined" && Model) === "function" ? _a : Object]),
+        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", void 0)
    ], Trait.prototype, "method", null);
    return Trait;
}
zbq4xfa0

zbq4xfa03#

我认为这个解决方法应该可行:

function mixin<T>(Model: new (...data: any[]) => T) {
+    type Model = typeof Model;
    
    class Trait {
        @register
        method(@validate input: Model) { }
    }
    return Trait;
}
pieyvz9o

pieyvz9o4#

感谢你的hack代码,但我想知道class语法既是类型又是值,为什么在mixins中我要使用typeof?

i2loujxw

i2loujxw5#

如果同时使用类的类型和值,您的hack代码在我的VS Code 1.71.0中显示类型错误:

- const register: MethodDecorator = () => { }
+ const register: (Model: new (...data: any[]) => any) => MethodDecorator =
    () => () => { }

const validate: ParameterDecorator = () => { }

function mixin<T>(Model: new (...data: any[]) => T) {
+    type Model = typeof Model;

    class Trait {
-        @register
+        @register(Model)
        method(@validate input: Model) { }
    }
    return Trait;
}

class TestModel {
    id = 0
}

class TestController extends mixin(TestModel) { }
ts[2502] Model is referenced directly or indirectly in its own type annotation.

但是,tsctypescript@4.8.3 中编译时与相同的 node_modules 一起工作正常...
TS playground 和 GitPod 的VS Code 1.69.2也运行正常...

mitkmikd

mitkmikd6#

@TechQuery
why should I use typeof in mixins?
A class declaration does create value and type entities but a variable only create the value one. In your case Model is just a variable refers to the class, so it doesn't create a type entity.
If I use both type & value of classes, your hack code shows a type error in my VS Code 1.71.0
I believe this is a bug, which is similar to #50191 and #50161 . I have reported it in #50795 .

wbgh16ku

wbgh16ku7#

最小复制品。

const A: new() => any = class B {}
function validate(...a: any[]) {}
class B {
    @validate test(a: typeof A) {}
}

编译为

看起来 typeof Expr 的行为在装饰器元数据中没有得到妥善处理。

wh6knrhe

wh6knrhe8#

感谢你的解释和问题报告。
当我再次打开GitPod的VS Code时,出现了相同的错误提示...
就像#50161所说的:有时候...

相关问题