Learn TypeScript w/ Mike North

Conditional Types

June 10, 2021

Table of Contents

Ternary operator with values

In a wide range of programming languages, we can find if/then/else logic. JavaScript provides a ternary1 operator that allows us to express this kind of logic concisely. For example.

const x = 16
const isXNegative = x >= 0 ? "no" : "yes"
const isXNegative: "no" | "yes"

The general format of this expression in the regular JS/TS world, when used with values (as shown in the snippet above) is:

condition ? exprIfTrue : exprIfFalse

Conditional types

Conditional types allow for types to be expressed using a very similar (basically, the same) syntax

class Grill {
startGas() {}
stopGas() {}
class Oven {
setTemperature(degrees: number) {}
type CookingDevice<T> = T extends "grill" ? Grill : Oven
let device1: CookingDevice<"grill">
let device1: Grill
let device2: CookingDevice<"oven">
let device2: Oven

Let’s remove everything except for the conditional type:

type CookingDevice<T> = T extends "grill" ? Grill : Oven

Expressing conditions

On the right side of the = operator, you can see the same three parts from our definition of a traditional value-based ternary operator

condition ? exprIfTrue : exprIfFalse
part expression
condition T extends "grill"
exprIfTrue Grill
exprIfFalse Oven

You probably notice the extends keyword in the condition. As of TypeScript v4. 3, is the only mechanism of expressing any kind of condition. You can think of it kind of like a >= comparison

Quiz: Expressing conditions

QUIZ: Conditional type - condition expressions

Let’s study a few examples of extends scenarios and see if we can figure out whether it will evaluate to true or false

1 64 extends number
2 number extends 64
3 string[] extends any
4 string[] extends any[]
5 never extends any
6 any extends any
7 Date extends {new (...args: any[]): any }
8 (typeof Date) extends {new (...args: any[]): any }
Click to reveal answers // SPOILER WARNING
type answer_1 = 64 extends number ? true : false
type answer_1 = true
type answer_2 = number extends 64 ? true : false
type answer_2 = false
type answer_3 = string[] extends any ? true : false
type answer_3 = true
type answer_4 = string[] extends any[] ? true : false
type answer_4 = true
type answer_5 = never extends any ? true : false
type answer_5 = true
type answer_6 = any extends any ? true : false
type answer_6 = true
type answer_7 = Date extends { new (...args: any[]): any }
? true
type answer_7 = false
: false
type answer_8 = typeof Date extends { new (...args: any[]): any }
? true
: false
type answer_8 = true

  1. Definition of ternary: three-part

© 2022 All Rights Reserved