Conditional types in TypeScript allow you to create types that depend on a condition. They are a powerful feature that can make your type definitions more flexible and expressive. This topic will cover the basics of conditional types, provide practical examples, and include exercises to help you understand and apply this concept.
Key Concepts
-
Basic Syntax: The basic syntax of a conditional type is
T extends U ? X : Y
, where:T
is the type you are checking.U
is the type you are comparing against.X
is the type returned ifT
extendsU
.Y
is the type returned ifT
does not extendU
.
-
Usage: Conditional types are often used to create more specific types based on certain conditions.
-
Distributive Conditional Types: When conditional types are applied to a union type, they are distributed over each member of the union.
Practical Examples
Example 1: Basic Conditional Type
type IsString<T> = T extends string ? "Yes" : "No"; // Usage type A = IsString<string>; // "Yes" type B = IsString<number>; // "No"
Explanation:
IsString
is a conditional type that checks ifT
extendsstring
.- If
T
is astring
, it returns"Yes"
, otherwise it returns"No"
.
Example 2: Conditional Type with Union
type ToArray<T> = T extends any ? T[] : never; // Usage type A = ToArray<string>; // string[] type B = ToArray<number>; // number[] type C = ToArray<string | number>; // string[] | number[]
Explanation:
ToArray
is a conditional type that converts a typeT
to an array ofT
.- If
T
is a union type, the conditional type is distributed over each member of the union.
Example 3: Nested Conditional Types
type TypeName<T> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : T extends undefined ? "undefined" : T extends Function ? "function" : "object"; // Usage type A = TypeName<string>; // "string" type B = TypeName<() => void>; // "function" type C = TypeName<{}>; // "object"
Explanation:
TypeName
is a nested conditional type that returns a string representation of the typeT
.- It checks multiple conditions to determine the type of
T
.
Exercises
Exercise 1: Create a conditional type IsArray<T>
that checks if a type T
is an array.
type IsArray<T> = T extends any[] ? "Array" : "Not Array"; // Test cases type Test1 = IsArray<string[]>; // "Array" type Test2 = IsArray<number>; // "Not Array" type Test3 = IsArray<[number, string]>; // "Array"
Exercise 2: Create a conditional type Flatten<T>
that flattens an array type T
.
type Flatten<T> = T extends (infer U)[] ? U : T; // Test cases type Test1 = Flatten<string[]>; // string type Test2 = Flatten<number[][]>; // number[] type Test3 = Flatten<number>; // number
Exercise 3: Create a conditional type ReturnType<T>
that extracts the return type of a function type T
.
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never; // Test cases type Test1 = ReturnType<() => string>; // string type Test2 = ReturnType<(x: number) => boolean>; // boolean type Test3 = ReturnType<() => void>; // void
Common Mistakes and Tips
-
Mistake: Forgetting that conditional types distribute over union types.
- Tip: Always consider how your conditional type will behave with union types.
-
Mistake: Using conditional types without understanding the
extends
keyword.- Tip: Make sure you understand how
extends
works in TypeScript before using conditional types.
- Tip: Make sure you understand how
-
Mistake: Overcomplicating type definitions with nested conditional types.
- Tip: Keep your type definitions as simple as possible and only use nested conditional types when necessary.
Conclusion
Conditional types are a powerful feature in TypeScript that allow you to create types based on conditions. They can make your type definitions more flexible and expressive. By understanding the basic syntax and usage of conditional types, you can leverage them to create more dynamic and adaptable types in your TypeScript code. Practice with the provided exercises to reinforce your understanding and apply conditional types effectively.
TypeScript Course
Module 1: Introduction to TypeScript
- What is TypeScript?
- Setting Up the TypeScript Environment
- Basic Types
- Type Annotations
- Compiling TypeScript
Module 2: Working with Types
Module 3: Advanced Types
Module 4: Functions and Modules
Module 5: Asynchronous Programming
Module 6: Tooling and Best Practices
- Linting and Formatting
- Testing TypeScript Code
- TypeScript with Webpack
- TypeScript with React
- Best Practices