TypeScript: Conditional Types Explained

Learn what conditionals are and how they are used in TypeScript

type ConditionalType = T extends U ? X : Y
type StringOrNot = SomeType extends string ? string : never;
type StringOrNot<T> = T extends string ? string : never;

Conditionals and Union Types

type AllSets = 'SET A' | 'SET B' | 'SET C'
type BorderStyles = 'solid' | 'dashed' | 'dotted' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset' | 'none' | 'hidden';function setBorder(val: BorderStyles): void {
...
}
type BorderWidths = 1 | 2 | 3 | 4 | 5;
type BorderStyle = `${BorderWidths}px ${BorderStyles}`;// Takes
// 1px solid | 1px dashed | ...
// 2px solid | 2px dashed | ...
// ... | ... | ...
type Border<T extends BorderWidth | 'none'> = T extends BorderWidth ? BorderStyle : 'none';
function setBorder<T extends BorderWidth | 'none'> (width: T, style: BorderStyles): Border<T> {
throw "unimplemented"
}

Filtering types with conditionals and never keyword

type StringOrNumberOnly<T> = T extends string | number ? T : never;type MyResult = StringOrNumberOnly<string | number | boolean>;// MyResult = string | number

Extract and Exclude utility types

type Extract<T, U> = T extends U ? T : never;
// some union type
type MyUnion = string | boolean | never;
// ResultType will extract from `MyUnion`
type ResultType = Extract<MyUnion, boolean | string | object>;
// ResultType = string | boolean;
type Exclude<T, U> = T extends U ? never : T;
// some union type
type MyUnion = string | boolean | never;
// attempt to exclude some types from `MyUnion`
type ResultType2 = Exclude<MyUnion, string>;
// ResultType2 = boolean;

Distributive vs non-distributive conditionals

type MyTypeFunction<T> = (() => T) extends () => string | number ? T : never;

Utility Types and their Conditionals

ReturnType<T>

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
type PromiseType<T> = T extends Promise<infer U> ? U : never;

Omit<Type, Keys>

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};

Bonus: Required<T>

type Required<T> = {
[P in keyof T]-?: T[P];
};

In Summary

Programmer and Author. Director @ JKRBInvestments.com. Creator of LearnChineseGrammar.com for iOS and Android.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store