-
Notifications
You must be signed in to change notification settings - Fork 12.8k
satisfies T
as type annotation
#52195
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
Comments
This seems like effectively a duplicate of #51556, since hypothetically you would write function getMagicNumber() {
if (Math.random() < 0.5) {
return 42;
} else {
return 0;
}
} satisfies (...args: any[]) => number; using that feature. #51556 also addresses a broader class of use cases (e.g. simultaneously constraining the parameter types as the return type) without introducing a type annotation syntax that only makes sense in a very small (1?) number of places. |
BTW, why isn't const usersResolver: satisfies UsersResolver = async () => {
const usersFromDb: User[] = /* ... access database ... */
return usersFromDb;
}; already solved by const usersResolver = async () => {
const usersFromDb: User[] = /* ... access database ... */
return usersFromDb;
} satisfies UsersResolver; ? What would the difference between these forms be, if any? |
The point would be that the variable definition |
While I agree with that as being an upside, I don't think it merits the trade-off compared to making a type psuedo-operator that only works in certain places. Tracking the use case at #51556 |
I, too, would like to see const x = (<K extends string>(obj: Record<K, V>) => obj)({
// hundreds of lines of code
});
// becomes:
const x = {
// hundreds of lines of code
} satisfies Record<string, V>; I disagree that the linked issue is a duplicate, because it would leave the type information at the end of the declaration where it is less likely to be seen, and would do nothing for declarations that aren't functions. I understand that the |
For anyone who supports this proposal, here is a TypeScript Language Service Plugin that might satisfy you... Hope it helps. |
i'm humbly (as someone who's not himself a maintainer of TypeScript) requesting that this proposal be re-opened for consideration on the grounds that #52195 (comment) 's
already exists in TypeScript in other forms (if i'm interpreting it correctly - e.g. type predicates) while prior arts such as Swift's
|
Uh oh!
There was an error while loading. Please reload this page.
Suggestion
π Search Terms
satisfies type annotation return impl trait
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
Add a new syntax
satisfies T
(whereT
is a type) that can be used at positions where a type annotation is expected.The above code should have the same meaning as the following code that utilizes TypeScript 4.9's
exp satisfies T
syntax.The behavior of the new
satisfies T
type annotation syntax can be summarized as follows:satisfies T
annotation is still left to inference.satisfies T
annotation, thesatisfies T
constraint is applied to its initiator.satisfies T
annotation, thesatisfies T
constraint is applied to allreturn
statements in it.π€ How about function parameters?
Function parameter could have a
satisfies T
annotation but it doesn't make any additional sence. If it is allowed anyway, it should be have the same as justT
.π Motivating Example
People have found TS 4.9's
exp satisfies T
syntax very useful, especially when one wants to explicitize a simple constraint against a variable and get contextual typing for its initializer, while also preserving its precise type for further type calculation.For ease of understanding what a variable is meant for, its type constraint should be put as close as possible to the declaration of variable. The ordinary type annotation plays very well in this view.
However, in order to extract more sophisticated information through type inference, we resort to the
exp satisfies T
syntax, which results in distance between variable definitiion and constraint: (note: assume we need contextual typing too, so that either type annotation orsatisfies
is necessary.)The proposed syntax has benefit of both ordinary type annotations and TS 4.9
exp satisfies T
syntax.You might think that inlay hints help recognizing the type of
classifyToOddAndEven
, but actual types are often too complex to be fully shown, nor as descriptive assatisfies
constraints. In practical situations actual types are only for type-level culculation and nor for human recognization.The
satifies T
annotation for return type is also proposed for similar motivation.Instead of applying the
satisfies T
constraint to the whole function type, just constraining its return type is sometimes enough.This is still preferable to the existing syntax that we don't have to repeat the
satisfies
constraint.Another small motivative example: Playground (thanks @progfay!)
π» Use Cases
My actual use case in mind is about writing GraphQL resolvers.
Thanks to Graphql Code Generator we can generate type defintion for resolvers. However, generated type definition are too permissive because it allows several different ways of writing resolvers. As a result, further type-level calculation using the generated type is hard.
With the proposed syntax, calculation of
ResultType
in the above example can be improved.The refined
ResultType
calculation then would be useful for unit testing where we want to use the knowledge thatusersResolver
returns aPromise<User[]>
, notPromise<(User | Promise<User>)[]>
.Note again: use of
satisfies
in any form is necessary in above examples, as we want to heavy-use contextual typing when writing actual GraphQL resolvers.π¨ Prior Art
The proposed feature is essentially the same as Rust's
impl Trait
. In Rust, actual type tends to become very complex and even impossible to write down as code.impl Trait
acts as a descriptive placeholder.The text was updated successfully, but these errors were encountered: