- Notifications
You must be signed in to change notification settings - Fork 13.2k
Conditional types#21316
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
Conditional types #21316
Uh oh!
There was an error while loading. Please reload this page.
Conversation
ahejlsberg commented Jan 20, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
# Conflicts: # src/compiler/checker.ts
# Conflicts: # src/compiler/checker.ts # src/compiler/types.ts # tests/baselines/reference/api/tsserverlibrary.d.ts # tests/baselines/reference/api/typescript.d.ts
leonadler commented Mar 19, 2018
Sorry if there is a more appropriate place to post this, but thanks for the new (albeit sometimes complicated) ways to express behavior! typeIsValidArg<T>=Textendsobject ? keyofTextendsnever ? false : true : true;typeNumberOfArgs<TextendsFunction>=Textends(a: infer A,b: infer B,c: infer C,d: infer D,e: infer E,f: infer F,g: infer G,h: infer H,i: infer I,j: infer J)=>any ? (IsValidArg<J>extendstrue ? 10 : IsValidArg<I>extendstrue ? 9 : IsValidArg<H>extendstrue ? 8 : IsValidArg<G>extendstrue ? 7 : IsValidArg<F>extendstrue ? 6 : IsValidArg<E>extendstrue ? 5 : IsValidArg<D>extendstrue ? 4 : IsValidArg<C>extendstrue ? 3 : IsValidArg<B>extendstrue ? 2 : IsValidArg<A>extendstrue ? 1 : 0) : 0;functionnumArgs<TextendsFunction>(fn: T): NumberOfArgs<T>{returnfn.lengthasany;}declarefunctionexampleFunction(a: number,b: string,c?: any[]): void;consttest=numArgs(exampleFunction);typePromisified<TextendsFunction>=Textends(...args: any[])=>Promise<any> ? T : (Textends(a: infer A,b: infer B,c: infer C,d: infer D,e: infer E,f: infer F,g: infer G,h: infer H,i: infer I,j: infer J)=> infer R ? (IsValidArg<J>extendstrue ? (a: A,b: B,c: C,d: D,e: E,f: F,g: G,h: H,i: I,j: J)=>Promise<R> : IsValidArg<I>extendstrue ? (a: A,b: B,c: C,d: D,e: E,f: F,g: G,h: H,i: I)=>Promise<R> : IsValidArg<H>extendstrue ? (a: A,b: B,c: C,d: D,e: E,f: F,g: G,h: H)=>Promise<R> : IsValidArg<G>extendstrue ? (a: A,b: B,c: C,d: D,e: E,f: F,g: G)=>Promise<R> : IsValidArg<F>extendstrue ? (a: A,b: B,c: C,d: D,e: E,f: F)=>Promise<R> : IsValidArg<E>extendstrue ? (a: A,b: B,c: C,d: D,e: E)=>Promise<R> : IsValidArg<D>extendstrue ? (a: A,b: B,c: C,d: D)=>Promise<R> : IsValidArg<C>extendstrue ? (a: A,b: B,c: C)=>Promise<R> : IsValidArg<B>extendstrue ? (a: A,b: B)=>Promise<R> : IsValidArg<A>extendstrue ? (a: A)=>Promise<R> : ()=>Promise<R>) : never);declarefunctionpromisify<TextendsFunction>(fn: T): Promisified<T>;declarefunctionexampleFunction2(a: number,b: string,c?: any[]): RegExp;consttest2=promisify(exampleFunction2); |
sirian commented Mar 27, 2018
sirian commented Mar 28, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
|
RyanCavanaugh commented Mar 28, 2018
@sirian please post code-fenced blocks instead of screenshots; no one wants to have to type in a dozen lines of code to add comments or observe behavior |
leonadler commented Mar 29, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@sirian are you asking a specific question? My example was not meant to be feature-complete, just a result of experimenting with 2.8 for a few minutes. It depends on typescripts |
sirian commented Mar 29, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@leonadler It was just a notice, that @RyanCavanaugh Mi fault, I was sure I attached code. |
sirian commented Mar 29, 2018
@leonadler I have an idea! We could use reverse extends check. Look at scratch: |
sirian commented Apr 12, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@ahejlsberg I think many users will copy types from your examples from #21316 (comment).
|
leonadler commented Apr 13, 2018
@sirian You seem to confuse "type A" with "object of type A". Similarily, when you write typeofObject==="function"TypeName<typeofObject>==="function"typeofObject.create(Object.prototype)==="object"TypeName<Object>==="object"classA{}typeofA==="function"TypeName<typeofA>==="function"typeof(newA())==="object"TypeName<A>==="object" |
pleerock commented May 10, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
How is it possible to do following? TextendsR[] ? BoxedArray<R> : BoxedValue<T> |
princemaple commented May 10, 2018
@pleerock T extends (infer R)[] |
pleerock commented May 10, 2018
@princemaple thanks it worked. Actually BoxedArray<T[number]> worked as well but such syntax wasn't obvious to me |



This PR introduces conditional types which add the ability to express non-uniform type mappings. A conditional type selects one of two possible types based on a condition expressed as a type relationship test:
The type above means when
Tis assignable toUthe type isX, otherwise the type isY. Evaluation of a conditional type is deferred when evaluation of the condition depends on type variables inTorU, but is resolved to eitherXorYwhen the condition depends on no type variables.An example:
Conditional types in which the checked type is a naked type parameter are called distributive conditional types. Distributive conditional types are automatically distributed over union types during instantiation. For example, an instantiation of
T extends U ? X : Ywith the type argumentA | B | CforTis resolved as(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y).In instantiations of a distributive conditional type
T extends U ? X : Y, references toTwithin the conditional type are resolved to individual constituents of the union type (i.e.Trefers to the individual constituents after the conditional type is distributed over the union type). Furthermore, references toTwithinXhave an additional type parameter constraintU(i.e.Tis considered assignable toUwithinX).Notice that
Thas the additional constraintany[]within the true branch ofBoxed<T>and it is therefore possible to refer to the element type of the array asT[number]. Also, notice how the conditional type is distributed over the union type in the last example.The distributive property of conditional types can conveniently be used to filter union types:
Conditional types are particularly useful when combined with mapped types:
Combining all of the above to create a
DeepReadonly<T>type that recursively makes all properties of an object read-only and removes all function properties (i.e. methods):Similar to union and intersection types, conditional types are not permitted to reference themselves recursively (however, indirect references through interface types or object literal types are allowed, as illustrated by the
DeepReadonly<T>example above). For example the following is an error:For further examples see the tests associated with the PR.
EDIT: See #21496 for type inference in conditional types.
Fixes#12215.
Fixes#12424.