Open rbuckton opened 3 years ago
Distilled down the inference example to a subjectively simpler one:
declare function decorator1(target: MyClass, prop: 'method1', index: 0) : void;
declare function decorator2(target: string , prop: any , index: any): void;
declare function decorator3(target: any , prop: 'wrong' , index: any): void;
declare function decorator4(target: any , prop: any , index: 99) : void;
class MyClass {
method1(@decorator1 foo: number) {}
// ^^^^^^^^^^^ should pass, now `Argument of type 'number' is not assignable to parameter of type '0'`
method2(@decorator2 foo: number) {}
// ^^^^^^^^^^^ should fail, now passes
method3(@decorator3 foo: number) {}
// ^^^^^^^^^^^ should fail, now passes
method4(@decorator4 foo: number) {}
// ^^^^^^^^^^^ should fail, now fails but for the wrong reason, message is the same as #1
}
decorator1(MyClass.prototype, 'method1', 0); // correct, no type errors
//
decorator2(MyClass.prototype, 'method1', 0); // correct, type error
// ^^^^^^^^^^^^^^^^^
decorator3(MyClass.prototype, 'method1', 0); // correct, type error
// ^^^^^^^^^
decorator4(MyClass.prototype, 'method1', 0); // correct, type error
// ^
It seems inference for decorators shipped in TypeScript 5, all my above testcases work as expected in TypeScript 5.
This is more of a meta issue that covers the following existing issues, but with some additional context:
33260 - Incorrect function type signature for ParameterDecorator
30102 - Infer method name for parameter decorator
The above issues reference various problems with decorators and decorator type checking. The following are some examples of issues I'd like to address:
Constructor parameter decorators receive
undefined
forpropertyKey
The definition of
ParameterDecorator
indicates thepropertyKey
isstring | symbol
, however constructor parameters receiveundefined
. Receivingundefined
is an intentional behavior, as it allows the decorator author to detect they are decorating a constructor's parameter. However, this is not correctly noted in the definition ofParameterDecorator
. That is the crux of #33260.However, there is more that we should be doing here, as we do not accurately check the type that should be passed for the
propertyKey
argument:The converse should also be addressed. If the
propertyKey
only allowsstring | symbol
, then the decorator should be an error when used on a constructor parameter:Parameter decorators do not check
target
typeIn this case, we are not correctly checking the type of the
target
parameter:And the same issue occurs when
target
is a function type:Constraining the type of a parameter
Constraining the type of a parameter is difficult (but not impossible) now that we have string literal types:
However, we again do not seem to check this correctly in decorators:
This is not a new issue, its likely existed since decorators were added.