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; // numberExample 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);


