Conditional types (TypeScript)
An explanation of TypeScript conditional types and an overview of some useful predefined ones
Basic idea
Conditional type: selects one of two possible types based on a condition, where the condition is something that tests for the relationship between types
General structure: T extends U ? X : Y
Examples (adapted from Conditional Types ):
declare function f<T extends boolean>(x: T): T extends true ? string : number;
let test1 = f(Math.random() < 0.5); // type: string | number
let test2 = f(true); // type: string
let test3 = f(false); // type: number;
type TypeName<T> = T extends string
? "string"
: T extends number
? "number"
: T extends boolean
? "boolean"
: T extends undefined
? "undefined"
: T extends Function
? "function"
: "object";
type T0 = TypeName<string>; // "string"
type T1 = TypeName<"a">; // "string"
type T2 = TypeName<true>; // "boolean"
type T3 = TypeName<() => void>; // "function"
type T4 = TypeName<string[]>; // "object"
The above were examples where the conditional type is resolved (the compiler can immediately decide what the resulting type is going to be)
Alternatively, the type can be deferred, meaning the compiler will decide when it has more info
Example (adapted from Conditional Types ):
interface Test {
propA: boolean;
propB: boolean;
}
declare function f<T>(x: T): T extends Test ? string : number;
// return type: T extends Test ? string : number
function test<U>(x: U) {
return f(x); // type
}
const result1 = test("a") // type: number
const result2 = test({ propA: true, propB: false }) // type: string
Predefined conditional types
Some conditional types already defined by the TypeScript language (see Predefined conditional types ):
Exclude
— Exclude fromT
those types that are assignable toU
Extract
— Extract fromT
those types that are assignable toU
NonNullable
— Excludenull
andundefined
fromT
ReturnType
— Obtain the return type of a function typeInstanceType
— Obtain the instance type of a constructor function type
Examples (adapted from Predefined conditional types ):
type Test1 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
type Test2 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
type Test3 = Exclude<string | number | (() => void), Function>; // string | number
type Test4 = Extract<string | number | (() => void), Function>; // () => void
type Test5 = NonNullable<string | number | undefined>; // string | number
type Test6 = NonNullable<(string[] | null | undefined>; // string[]
type Test7 = ReturnType<() => boolean> // boolean