-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refine type checking for class accessor when using decorator #52559
Comments
I'm not seeing how this would happen. In the by far most-common case, the source code of the decorator is not visible, so shouldn't really be thought of as a thing that can be analyzed. |
Is it possible to do that by checking the return type of function dec1() {
return {
init(): NonNull {
// ...
}
}
}
function dec2() {
return {
init(): NonNull | undefined {
// ...
}
}
} |
@rbuckton any input? |
My current thinking is that we would handle this via the function dec() {
return {
init<T>(initialValue: T | undefined): T {
...
}
} Where the body of Another use case might be a dependency injection system, where In the type system, we would need to infer the type of the property from the return type of |
When starting to try to adopt the accessor decorator support in TS 5.x in real-world use cases (including dependency injection) we hit this need immediately. The decorator returning a type with (A possibly-separate-but-related issue is that the type of the field -- whether considered initialized or not -- is unambiguously the
This is a weird explanation when the whole raison d'Γͺtre of typescript is to carry type information from the place where a function is implemented to the place where it is consumed. The existing type signatures of decorator functions already contain enough information to infer whether type GetReturns<Result> = Result extends ClassAccessorDecoratorResult<
unknown,
infer Value
>
? Result['get'] extends undefined
? unknown
: Value
: unknown;
type InferredAccessorType<Decorator> = Decorator extends (
...args: any
) => infer Result
? GetReturns<Result>
: unknown;
type Example = InferredAccessorType<typeof myDecoratorFunction>; |
Are there any plans to resolve this issue? |
An additional problem with the current implementation is that interface ClassAccessorDecoratorResult<This, Value> {
get?(this: This): Value;
set?(this: This, value: Value): void;
init?(this: This, value: Value): Value;
} However, because the decorator can add a separate getter and setter, it is valid to have a getter/setter combo with different signatures. E.g. interface ClassAccessorDecoratorResult<This, GetValue, SetValue> {
get?(this: This): GetValue;
set?(this: This, value: SetValue): void;
init?(this: This, value: GetValue): GetValue;
} For example, you might have a getter that returns an asynchronous value ( |
Suggestion
π Search Terms
decorator, class accessor, auto-accessor, types, null checks.
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
If a class accessor decorator will always add an initial value for the decorated accessor, TypeScript should infer that the accessor is always non-null, even if no initial value in its original declaration.
π Motivating Example
See playground.
The decorator
dec
will always initialize the accessor with a non-null value, but TS reports an error on@dec accessor data: Wrapper<string>;
. It says "Property 'data' has no initializer and is not definitely assigned in the constructor" whenstrictNullChecks
is enabled.Are there any workarounds, other than putting an
!
afterdata
, to make the type checking works?π» Use Cases
The text was updated successfully, but these errors were encountered: