Using extends and Type Logic


Learn how to use conditional types in TypeScript to create dynamic type logic. This module explains the extends keyword, conditional type expressions, and practical real-world examples.

1. Using extends in Conditional Types

Conditional types allow you to define types that depend on a condition. The extends keyword is used to express the condition.

Basic Example


type IsString<T> = T extends string ? "Yes" : "No";

type Test1 = IsString<string>; // "Yes"
type Test2 = IsString<number>; // "No"

This creates a type that evaluates differently based on whether T extends string.

2. Conditional Logic in Types

Conditional types can be combined with generics to create flexible and reusable type logic.

Example: Extracting Type


type ElementType<T> = T extends (infer U)[] ? U : T;

type NumberArray = number[];
type NumberType = ElementType<NumberArray>; // number

type StringType = ElementType<string>; // string

The infer keyword allows extracting a type from a structure dynamically.

Example: Exclude and Extract


type T1 = string | number | boolean;
type OnlyString = Extract<T1, string>; // string
type NotString = Exclude<T1, string>; // number | boolean

Built-in TypeScript utility types like Extract and Exclude are based on conditional types.

3. Practical Examples

Example: Nullable Types


type NonNullable<T> = T extends null | undefined ? never : T;

type Name = NonNullable<string | null | undefined>; // string

Example: Function Return Type


type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

function getUser() {
return { id: 1, name: "Muni" };
}

type UserType = ReturnType<typeof getUser>; // { id: number; name: string; }

Conditional types are highly useful for creating advanced type utilities and improving type inference in complex applications.

Conclusion

Conditional types in TypeScript provide powerful tools for creating dynamic, type-safe logic. By using extends, infer, and conditional expressions, developers can design flexible types that adapt to various scenarios, enabling more robust and maintainable code.