Allowing `infer` after `extends T` in conditional types would simplify complicated type definitions massively
See original GitHub issueSuggestion
š Search Terms
- distributed conditional types
- infer keyword
ā Viability Checklist
My suggestion meets these guidelines:
- This wouldnāt be a breaking change in existing TypeScript/JavaScript code
- This wouldnāt change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isnāt a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScriptās Design Goals.
ā Suggestion
Doing this would allow the complete removal of an entire branch, and itās much more intuitive (the hanging infer
stumped me a whole lot when I was learning).
Before:
InferringType<T> = T extends infer U ? U extends SomeConcreteType ? U : never : never
After:
InferringType<T> = T extends SomeConcreteType infer U ? U : never
Alternatives
- Something consistent with the
as
keyword in template string literal types e.g.
InferringType<T> = T extends SomeConcreteType as U ? U : never
- No extra syntax, just smart control flow analysis on the type variable.
InferringType<T> = T extends SomeConcreteType
? T // T extends SomeConcreteType on this branch
: never // T does not extend SomeConcreteType on this branch
š Motivating Example
This playground link - has some documentation that should provide some context for the following code, but this is a pretty universal pattern anyway.
Before:
type InferEventFromTypeMatch<TypeMatch extends string> = TypeMatch extends infer InferredTypeMatch
? InferredTypeMatch extends Event['type']
? Extract<Event, AbstractEvent<InferredTypeMatch, any>>
: InferredTypeMatch extends `${infer WildcardedTypeMatch}*`
? Event extends infer EventCase
? EventCase extends { type: `${WildcardedTypeMatch}${any}` }
? EventCase
: never
: never
: never
: never
After:
type InferEventFromTypeMatch0<TypeMatchString extends string> =
TypeMatchString extends Event['type'] infer ExactTypeMatchString // Can give a much more meaningful label
? Extract<Event, AbstractEvent<ExactTypeMatchString, any>>
: InferredTypeMatch extends `${infer WildcardedTypeMatch}*`
? Event extends { type: `${WildcardedTypeMatch}${any}` } infer WildcardTypeMatch // Can give a much more meaningful label here too
? WildcardTypeMatch
: never
: never // Only two hanging nevers, rather than four
š» Use Cases
Issue Analytics
- State:
- Created 2 years ago
- Comments:10 (5 by maintainers)
Top Results From Across the Web
Advanced TypeScript: The Power and Limitations of ... - Medium
The infer keyword can go inside of a conditional type to the right of the extends keyword. Using infer is asking TypeScript to...
Read more >Documentation - Conditional Types - TypeScript
Create types which act like if statements in the type system. ... We can then use that conditional type to simplify our overloads...
Read more >Understanding infer in TypeScript - LogRocket Blog
The infer keyword and conditional typing in TypeScript allows us to take a type and isolate any piece of it for later use....
Read more >Understanding null safety - Dart
Since non-nullable types are modeled as subtypes of nullable types, implicit downcasts would let you pass a String? to something expecting a String...
Read more >The Logic of Conditionals - Stanford Encyclopedia of Philosophy
Logics of conditionals deal with inferences involving sentences of the form ... Our goal in particular will be to allow readers to orientĀ ......
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Yes, but
M
doesnāt need to be covered byDottedKey
for my specific use case. So I donāt really care at the moment.I think what youāre looking for already exists, with a slightly different syntax:
Translating your second version directly:
But in your specific example you donāt need it at all:
Thereās a cost to inference, so in idiomatic code we do not use it to rename types. Narrowing a type with
T extends Something
and then usingT
is not hard to follow, once you get used to it.