TypeScript
TypeScript copied to clipboard
[Bug] Mixin parameters failed to use as Method Parameter types of Inner Classes
🔎 Search Terms
mixin, parameter, class method, type declaration, decorator
🕗 Version & Regression Information
- This is a crash
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about mixin & parameter
⏯ Playground Link
Playground link with relevant code
💻 Code
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) { }
🙁 Actual behavior
Type checking crashed
error TS2749: 'Model' refers to a value, but is being used as a type here. Did you mean 'typeof Model'?
method(@validate input: Model) {
~~~~~
Compiled seems to work
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;
}
🙂 Expected behavior
Shown sample code works, so that projects with Decorator frameworks will be much simpler, like what my service scaffold does: idea2app/REST-Node-ts#1
The error message is correct. Model refers to a value of a function parameter and you should use typeof to refer to the type of it.
See https://www.typescriptlang.org/docs/handbook/2/typeof-types.html.
The error message is correct.
Modelrefers to a value of a function parameter and you should usetypeofto refer to the type of it. See https://www.typescriptlang.org/docs/handbook/2/typeof-types.html.
I know that typeof is the "correct syntax", but if I change it like that, Parameter Decorator will failed to get emited classes:
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;
}
I think this workaround should work:
function mixin<T>(Model: new (...data: any[]) => T) {
+ type Model = typeof Model;
class Trait {
@register
method(@validate input: Model) { }
}
return Trait;
}
@whzx5byb Thanks your hack code, but I wonder that class syntax is both type & value, why should I use typeof in mixins?
@whzx5byb If I use both type & value of classes, your hack code shows a type error in my 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.
but tsc compiling with the same [email protected] in node_modules works fine...
TS playground & GitPod's VS Code 1.69.2 works fine, too...
@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 https://github.com/microsoft/TypeScript/issues/50191 and https://github.com/microsoft/TypeScript/issues/50161. I have reported it in https://github.com/microsoft/TypeScript/issues/50795.
const A: new() => any = class B {}
function validate(...a: any[]) {}
class B {
@validate test(a: typeof A) {}
}
compiles to
It looks like the behavior of typeof Expr is not handled properly in decorator metadata.
@whzx5byb Thanks your explanation & issue reporting.
When I open my GitPod VS Code again, the same error hints...
Just like #50161 said: sometimes...