Step 14 – Advanced TypeScript Features

Conditional Types

Conditional types allow you to conditionally choose a type based on a condition. The syntax for a conditional type is T extends U ? X : Y, where T is the type being tested, U is the condition being tested against, X is the type returned if the condition is true, and Y is the type returned if the condition is false.

For example, let’s say you have a function that takes a type T and returns a new type based on whether T is an array or not:

type IsArray<T> = T extends Array<any> ? true : false;
type MyType = IsArray<number>; // MyType is false
type MyOtherType = IsArray<number[]>; // MyOtherType is true

In this example, IsArray is a conditional type that tests whether T extends Array<any>. If it does, the type true is returned; if it doesn’t, the type false is returned. The types MyType and MyOtherType demonstrate how the IsArray type works.

Mapped Types

Mapped types allow you to create new types by mapping over an existing type. The syntax for a mapped type is { [P in K]: T }, where P is the property key, K is a union of property keys, and T is the type of the property.

For example, let’s say you have an interface with a bunch of optional properties, and you want to create a new interface that makes all those properties required:

interface MyInterface {
  foo?: number;
  bar?: string;
}

type RequiredMyInterface = { [P in keyof MyInterface]-?: MyInterface[P] };

In this example, RequiredMyInterface is a mapped type that maps over the keys of MyInterface. The -? makes each property required, and the type MyInterface[P] sets the type of the property.

Type Aliases

Type aliases allow you to create a new name for an existing type. The syntax for a type alias is type NewType = OldType.

For example, let’s say you have a function that takes a callback and returns a new function that takes the same arguments as the original function, but with an additional callback parameter:

type Callback<T> = (arg: T) => void;
type NewCallback<T> = (arg: T, callback: Callback<T>) => void;

function addCallback<T>(fn: (arg: T) => void): NewCallback<T> {
  return (arg, callback) => {
    fn(arg);
    callback(arg);
  };
}

In this example, Callback and NewCallback are type aliases that define the types of the callback functions used by addCallback.

Text Diagram

Here’s a text diagram to help you understand how conditional types and mapped types work:

MyType:
T extends Array<any> ? true : false

MyOtherType:
T extends Array<any> ? true : false

RequiredMyInterface:
{ [P in keyof MyInterface]-?: MyInterface[P] }

In this diagram, MyType and MyOtherType are examples of conditional types, while RequiredMyInterface is an example of a mapped type.

Code Examples

Here are some additional code examples to help you understand these advanced TypeScript features:

Conditional Types

type IfEquals =
(() => T extends X ? 1 : 2) extends
(() => T extends Y ? 1 : 2) ? A : B;

type MyType = IfEquals; // MyType is false
type MyOtherType = IfEquals; // MyOtherType is false

Mapped Types

interface MyObject {
  foo: number;
  bar: string;
}

type ReadonlyMyObject = { readonly [P in keyof MyObject]: MyObject[P] };

const obj: ReadonlyMyObject = { foo: 1, bar: "hello" };
obj.foo = 2; // Error: Cannot assign to 'foo' because it is a read-only property

In this example, we define an interface MyObject with two properties, foo and bar. We then create a mapped type ReadonlyMyObject that maps over the keys of MyObject and sets each property to readonly. Finally, we create an object obj of type ReadonlyMyObject, which prevents us from modifying any of its properties.

Type Aliases

type User = {
  id: number;
  name: string;
};

type UserID = User["id"];

const user: User = { id: 1, name: "John" };
const userID: UserID = user.id; // userID is of type number

In this example, we define a type User with two properties, id and name. We then create a type alias UserID that refers to the id property of User. Finally, we create an object user of type User and extract its id property into a variable userID of type UserID.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.