Conditional Types

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

Professional TypeScript Masterclass Lessons

1.Introduction
free
⏱️ 1:54
2.Setup
free
⏱️ 5:44
3.Primitive Types
free
⏱️ 1:42
4.Instance Types
free
⏱️ 1:52
5.Arrays And Tuples
free
⏱️ 1:38
6.Objects
free
⏱️ 1:33
7.const declarations
free
⏱️ 1:03
8.Function Types
free
⏱️ 1:57
9.Structural Typing
free
⏱️ 2:10
10.Classes in TypeScript
free
⏱️ 1:48
11.Target Compiler Option
free
⏱️ 2:37
12.Generics
⏱️ 3:02
13.Special Types any And unknown
⏱️ 2:00
14.JavaScript to TypeScript
⏱️ 1:32
15.Frontend Projects
⏱️ 3:49
16.Type Assertions
⏱️ 2:15
17.Type Casting
⏱️ 1:16
18.Modules
⏱️ 1:55
19.Type Declarations
⏱️ 4:25
20.Creating NPM packages
⏱️ 3:20
21.Async Await
⏱️ 3:05
22.Running in NodeJS
⏱️ 1:40
23.Lexical this
⏱️ 2:34
24.readonly Modifier
⏱️ 1:59
25.Union Types
⏱️ 2:57
26.Literal Types
⏱️ 2:58
27.Type Narrowing
⏱️ 4:19
28.Discriminated Unions
⏱️ 3:29
29.Class Parameter Properties
⏱️ 1:02
30.Strict Compiler Option
⏱️ 6:18
31.null vs undefined
⏱️ 4:19
32.Intersection Types
⏱️ 2:03
33.Optional Modifier
⏱️ 2:47
34.Non Null Assertion Operator
⏱️ 3:40
35.Interfaces
⏱️ 2:28
36.Interface Declaration Merging
⏱️ 1:01
37.Types vs Interfaces
⏱️ 2:16
38.never Type
⏱️ 3:00
39.implements Keyword
⏱️ 1:25
40.Definite Assignment Assertion
⏱️ 2:31
41.User Defined Type Guards
⏱️ 2:02
42.Assertion Functions
⏱️ 3:42
43.Function Overloading
⏱️ 4:15
44.Call Signatures
⏱️ 2:53
45.Abstract Classes
⏱️ 1:53
46.Index Signatures
⏱️ 3:08
47.Readonly Arrays and Tuples
⏱️ 2:58
48.Double Assertions
⏱️ 2:20
49.const Assertions
⏱️ 3:55
50.this Parameter
⏱️ 2:33
51.Generic Constraints
⏱️ 2:43
52.typeof Type Operator
⏱️ 2:12
53.Lookup Types
⏱️ 3:12
54.keyof Type Operator
⏱️ 3:55
55.Conditional Types
⏱️ 4:39
56.Contitional Types with Unions and never
⏱️ 3:32
57.infer Keyword and `ReturnType<T>`
⏱️ 3:47
58.Mapped Types
⏱️ 2:48
59.Mapped Type Modifiers
⏱️ 3:37
60.Template Literal Type
⏱️ 4:28
61.Partial<T>
⏱️ 1:27
62.Required<T>
⏱️ 1:36
63.Readonly<T>
⏱️ 1:34
64.Record<K, T>
⏱️ 4:05
65.Project References
⏱️ 4:18
66.undefined vs. optional
⏱️ 2:48
67.satisfies Operator
⏱️ 2:42
68.PropertyKey Type
⏱️ 0:57
69.ThisType<T>
⏱️ 4:11
70.Awaited<T>
⏱️ 4:12
71.String Manipulation Types
⏱️ 3:36
72.Mapped Types as Clauses
⏱️ 4:01
73.Union vs Intersection Mental Model
⏱️ 3:36
74.Enums are Bad
⏱️ 8:11

Conditional Types

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

JavaScript Conditional

The JavaScript conditional, also called ternary, is used to map an input to two different output depending on a condition e.g.:

const isNumber = (value: unknown) =>
typeof value === 'number'
? 'number'
: 'other';

const withNumber = isNumber(123);
const withOther = isNumber('hello');

Conditional Type Function

Just like the JavaScript runtime conditional, TypeScript compile type conditional can map an input Type to different output Types depending on a condition.

  • Inputs are collected using a Generic Argument
  • Conditions use extends to check for a constraint
  • Output is another type

For example

type IsNumber<T> =
T extends number
? 'number'
: 'other';

type WithNumber = IsNumber<number>;
type WithOther = IsNumber<string>;
  • T is an input type
  • extends number is the check
  • 'number' and 'other' are the output literal types.

Use Case

You can use it to add annotation for pretty powerful functions e.g. the typeName function is annotated using the TypeName conditional type:

export type TypeName<T> =
T extends string ? 'string' :
T extends number ? 'number' :
T extends boolean ? 'boolean' :
T extends undefined ? 'undefined' :
T extends symbol ? 'symbol' :
T extends bigint ? 'bigint' :
T extends Function ? 'function' :
'object';

function typeName<T>(t: T): TypeName<T> {
return typeof t as TypeName<T>;
}

const str = typeName('hello world'); // str: 'string'
const num = typeName(123); // num: 'number'
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

Conditional types in TypeScript allow you to create conditional logic functions within the type system. Let's look at an example. Here we have a generic type is number. It takes the type as a generic input, stores it in type T, and then checks if type T extends the type number, and if that condition is true, returns the literal type number, otherwise returns the literal type other. These types are called conditional types Because of the use of the conditional operator, this is modeled after the conditional operator.

00:32

Within JavaScript, people often also call this the ary operator because this is the only operator within JavaScript that has three inputs. A condition a result when the condition is true and a result when the condition is false. Now our is number utility function over here can be invoked with any JavaScript value. For example, it can be invoked with a number or it can be invoked with a string. The same is true of our is number type function. It can be invoked by passing in a generic. For the type T for example, we can pass in number S type T,

01:07

or we can pass in something else like a string. The logic for these types is run within the TypeScript type system. When the type number is passed in four T, TypeScript sees that number extends number. It understands that to be true and returns the literal type number, and we can see that when we hover over the result. Similarly, when the type string is passed in four T, TypeScript sees string extends number. It understands that to be false and returns a little type other, and we can see that when we hover over the results.

01:42

This comparison between JavaScript and TypeScript gives you a mental model of how to think about conditional types. The key difference is that while the JavaScript is executed by the JavaScript runtime and works with runtime values, the type function is executed by the TypeScript compiler at compile time and works with TypeScript types. Now let's look at a use case of conditional types. Here we have a TypeScript conditional type that works with all of the types that are supported by the JavaScript type of operator. We can use this conditional type as the return type

02:16

of a generic function within the function body. We simply return the result of the JavaScript type of operator. Our type name T is modeling at compile time. What the JavaScript type of T will do at runtime. Let's invoke this function with all of the primitives that the JavaScript runtime supports for all of these cases. TypeScript will correctly infer at compile time what the return value will be at runtime. For example, when it is invoked with a value undefined, the JavaScript runtime returns type of undefined,

02:50

which will be the literal string undefined, and we've correctly inferred that if you hover over the result. The same is true for other invocations As well. We successfully inferred at compile time the runtime return result of all of these function calls. Let's walk through this Boolean example. When we invoke type name with the literal true TypeScript infers the type of the input argument to be Boolean and therefore T is bullion. Now the return type is annotated to be type name of bullion. TypeScript goes through the conditional type

03:26

and the only condition that matches is T extends bullion and therefore TypeScript infers the return type to be the literal bullion. And we can see that inference when we hover over the results. Now, one thing that you might find surprising is that the inferred result of invoking the function with now is the literal type object. And no, this is not a bug. This is just how the JavaScript runtime works with type of now it actually returns the string object. But fortunately with TypeScript,

03:58

our type name function can be better than the built-in type of operator in JavaScript. First, we add an additional condition to the type name conditional type to check FT exchange now and return the literal now. And then within our run type, type name function, we add a condition to check. IFT is now to return the literal now, and with these two changes in place, our runtime result will be now and it is also inferred correctly at compile time. Now we can easily keep on adding other conditions to the conditional type

04:29

and to our runtime function to make a type nine utility that is specific to our project and meets our needs more than the built in JavaScript runtime support.

Professional TypeScript Masterclass

Professional TypeScript Masterclass

1.Introduction
free
⏱️ 1:54
2.Setup
free
⏱️ 5:44
3.Primitive Types
free
⏱️ 1:42
4.Instance Types
free
⏱️ 1:52
5.Arrays And Tuples
free
⏱️ 1:38
6.Objects
free
⏱️ 1:33
7.const declarations
free
⏱️ 1:03
8.Function Types
free
⏱️ 1:57
9.Structural Typing
free
⏱️ 2:10
10.Classes in TypeScript
free
⏱️ 1:48
11.Target Compiler Option
free
⏱️ 2:37
12.Generics
⏱️ 3:02
13.Special Types any And unknown
⏱️ 2:00
14.JavaScript to TypeScript
⏱️ 1:32
15.Frontend Projects
⏱️ 3:49
16.Type Assertions
⏱️ 2:15
17.Type Casting
⏱️ 1:16
18.Modules
⏱️ 1:55
19.Type Declarations
⏱️ 4:25
20.Creating NPM packages
⏱️ 3:20
21.Async Await
⏱️ 3:05
22.Running in NodeJS
⏱️ 1:40
23.Lexical this
⏱️ 2:34
24.readonly Modifier
⏱️ 1:59
25.Union Types
⏱️ 2:57
26.Literal Types
⏱️ 2:58
27.Type Narrowing
⏱️ 4:19
28.Discriminated Unions
⏱️ 3:29
29.Class Parameter Properties
⏱️ 1:02
30.Strict Compiler Option
⏱️ 6:18
31.null vs undefined
⏱️ 4:19
32.Intersection Types
⏱️ 2:03
33.Optional Modifier
⏱️ 2:47
34.Non Null Assertion Operator
⏱️ 3:40
35.Interfaces
⏱️ 2:28
36.Interface Declaration Merging
⏱️ 1:01
37.Types vs Interfaces
⏱️ 2:16
38.never Type
⏱️ 3:00
39.implements Keyword
⏱️ 1:25
40.Definite Assignment Assertion
⏱️ 2:31
41.User Defined Type Guards
⏱️ 2:02
42.Assertion Functions
⏱️ 3:42
43.Function Overloading
⏱️ 4:15
44.Call Signatures
⏱️ 2:53
45.Abstract Classes
⏱️ 1:53
46.Index Signatures
⏱️ 3:08
47.Readonly Arrays and Tuples
⏱️ 2:58
48.Double Assertions
⏱️ 2:20
49.const Assertions
⏱️ 3:55
50.this Parameter
⏱️ 2:33
51.Generic Constraints
⏱️ 2:43
52.typeof Type Operator
⏱️ 2:12
53.Lookup Types
⏱️ 3:12
54.keyof Type Operator
⏱️ 3:55
55.Conditional Types
⏱️ 4:39
56.Contitional Types with Unions and never
⏱️ 3:32
57.infer Keyword and `ReturnType<T>`
⏱️ 3:47
58.Mapped Types
⏱️ 2:48
59.Mapped Type Modifiers
⏱️ 3:37
60.Template Literal Type
⏱️ 4:28
61.Partial<T>
⏱️ 1:27
62.Required<T>
⏱️ 1:36
63.Readonly<T>
⏱️ 1:34
64.Record<K, T>
⏱️ 4:05
65.Project References
⏱️ 4:18
66.undefined vs. optional
⏱️ 2:48
67.satisfies Operator
⏱️ 2:42
68.PropertyKey Type
⏱️ 0:57
69.ThisType<T>
⏱️ 4:11
70.Awaited<T>
⏱️ 4:12
71.String Manipulation Types
⏱️ 3:36
72.Mapped Types as Clauses
⏱️ 4:01
73.Union vs Intersection Mental Model
⏱️ 3:36
74.Enums are Bad
⏱️ 8:11