TypeScript Conditional Types

Conditional Type Expression

SomeType extends OtherType ? TrueType : FalseType;

Basic Usages

Example 1

type NumberOrNot<T> = T extends number ? string : never;

Example 2

type StringOrNot<T> = T extends string ? string : never;

Example 3

type BooleanOrNumberOnly<T> = T extends boolean | number ? T : never;

type NewType = StringOrNumberOnly<string | number | boolean>;

const a1: NewType = true; // boolean

const a2: NewType = 23; // number

Example 4

type TypeStringName<T> = T extends string ? 'string' : T extends boolean ? 'boolean' : T extends Error ? 'error' : never;

type STRING_TYPE = TypeStringName<'hello'>; // 'string'
type BOOLEAN_TYPE = TypeStringName<false>; // 'boolean'
type ERROR_TYPE = TypeStringName<TypeError>; // 'error'
interface Animal {
  live(): void;
}
interface Dog extends Animal {
  woof(): void;
}
 
type Example = Dog extends Animal ? number : string;

type Example2 = RegExp extends Animal ? number : string;

Conditional Type Constraint

Wrong Usage

type MessageOf<T> = T['message'];

// TypeScript errors in this line because T doesn't have `message` field.

Correct Usage

MessageOf type has a generic type T and T should have message field.

type MessageOf<T extends { message: unknown }> = T['message'];

type Email = { message: string };

type EmailMessageContents = MessageOf<Email>;

Email type has a message field in line 3 in the above code.

So, EmailMessageContents type will be string due to { message: string } as shown below popup;

Assume that Dog type doesn't have message field. So TypeScript errors in line 9 as shown below;

Some Usages

Example 1

interface IdLabel {
    id: number;
}

interface NameLabel {
    name: string;
}

type NameOrId<T extends number | string> = T extends number ? IdLabel : NameLabel;

function createLabel<T extends number | string>(idOrName: T): NameOrId<T> {
    throw "unimplemented";
}

const a1 = createLabel('TypeScript');

const a2 = createLabel(2893);

const a3 = createLabel(Math.random() ? 'hello' : 333);

Leave a Reply

Your email address will not be published.