menu

JavaScript/Typescript - 16 Topics

DEEP DIVE INTO

JavaScript/Typescript

Topic:conditional types

menu

Conditional types in TypeScript are a powerful and flexible feature that allows you to define types based on conditions. Conditional types enable you to create complex type transformations and mappings that depend on the characteristics of other types. They are often used in conjunction with TypeScript's type system to achieve more dynamic and expressive type checking. Let's dive deep into conditional types in TypeScript:

Syntax:

Conditional types are defined using the extends keyword and the ? (question mark) operator. The basic syntax looks like this:

javascripttype MyType = T extends U ? X : Y;
  1. T is the type you want to check.

  2. U is the type you want to compare it to.

  3. X is the resulting type if the condition is true.

  4. Y is the resulting type if the condition is false.

Basic Usage:

Here's a simple example to illustrate the use of conditional types:

javascripttype IsString = T extends string ? true : false;

const a: IsString<"Hello"> = true;    // true
const b: IsString<42> = false;        // false
const c: IsString = false;  // false

In this example, the IsString type checks if the type T extends string. If it does, it returns true; otherwise, it returns false.

Distributive Conditional Types:

Conditional types are distributive, meaning they automatically distribute over union types. This behavior is often used to transform the types of elements within a union.

javascripttype StringOrNumber = T extends string ? string : number;

const x: StringOrNumber<"Hello" | 42> = "Hello"; // "Hello"
const y: StringOrNumber = 123;    // 123

In this example, the conditional type StringOrNumber is applied to a union type, and it transforms the types within the union.

Keyof and Lookup Types:

Conditional types are frequently used with keyof and lookup types to create mapped types that transform property values based on conditions.

javascripttype MakeNullable = {
  [P in K]: T[P] | null;
};

interface User {
  name: string;
  age: number;
}

type NullableUser = MakeNullable;

const user: NullableUser = { name: "Alice", age: null };

In this example, the MakeNullable type transforms the properties of User by making them nullable.

Advanced Usage:

Conditional types can be used for more complex scenarios, such as mapping over tuples or arrays, performing conditional merging of types, creating conditional type guards, and more. They offer a high level of expressiveness and can be used to model intricate type manipulations.

javascripttype Flatten = T extends Array ? U : T;

type Tuple = [string, number, boolean];
type Flattened = Flatten; // string | number | boolean

In this example, the Flatten type is used to extract the element type of an array or return the input type if it's not an array.

Type Guards:

Conditional types are often used to create type guards that check if a value is of a certain type.

javascripttype IsArray = T extends any[] ? true : false;

function isArray(value: T): value is T[] {
  return Array.isArray(value);
}

if (isArray([1, 2, 3])) {
  // Here, TypeScript knows value is an array
}

In this example, the isArray function serves as a type guard that uses a conditional type to check if the value is an array.

Conditional types in TypeScript provide a versatile way to define types that depend on conditions and characteristics of other types. They are commonly used in more advanced type-related scenarios and are an important tool for achieving strong typing and expressiveness in TypeScript code. When used effectively,conditional types can lead to more robust and error-resistant TypeScript code.

1280 x 720 px