TypeScript: Advanced Types
Mapped Types
📘 typescriptlang.org > mapped types
Mapped types allow you to create new types by transforming properties of an existing type. They are particularly useful for creating variations of a type, such as making all properties optional, readonly, or converting types of properties. Key Concepts
- Mapping Over a Type's Properties: You can create a new type by iterating over the properties of an existing type.
- Template Literals in Keys: Mapped types can use template literals to transform the keys.
- Modifying Property Modifiers: You can make properties optional, required, or readonly using modifiers.
Syntax
type MappedType = {
[Property in keyof ExistingType]: TransformedType;
};
Example
Create a new type where all properties of an existing type are of type string.
type Person = {
name: string;
age: number;
};
type StringifiedPerson = {
[Key in keyof Person]: string;
};
// StringifiedPerson is equivalent to:
// {
// name: string;
// age: string;
// }
Create a new type where all properties are optional.
type Partial<T> = {
[P in keyof T]?: T[P];
};
type Person = {
name: string;
age: number;
};
type PartialPerson = Partial<Person>;
// PartialPerson is equivalent to:
// {
// name?: string;
// age?: number;
// }
Create a new type where all properties are readonly.
type Readonly<T> = {
[P in keyof T]: Readonly<T[P]>;
};
type Person = {
name: string;
age: number;
};
type ReadonlyPerson = Readonly<Person>;
// ReadonlyPerson is equivalent to:
// {
// readonly name: string;
// readonly age: number;
// }
Create a new type that removes readonly and ? modifiers from properties.
type Mutable<T> = {
-readonly [P in keyof T]-?: T[P];
};
type ReadonlyPerson = {
readonly name: string;
readonly age?: number;
};
type MutablePerson = Mutable<ReadonlyPerson>;
// MutablePerson is equivalent to:
// {
// name: string;
// age: number;
// }
Conditional Types
📘 typescriptlang.org > conditional types
Conditional types in TypeScript allow you to define types that depend on a condition, similar to ternary expressions in JavaScript. They enable you to create more flexible and expressive types by making decisions based on other types.
Syntax
T extends U ? X : Y
Samples
Basic Conditional Type
Create a type that evaluates to true if a type is string, otherwise false.
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
Filtering Types
Use conditional types to filter out null and undefined from a union type.
type NonNullable<T> = T extends null | undefined ? never : T;
type A = NonNullable<string | number | null | undefined>; // string | number
Inferring Types
Conditional types can infer types using the infer keyword.
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function foo(): string {
return "hello";
}
type FooReturnType = ReturnType<typeof foo>; // string
Distributive Conditional Types
Conditional types distribute over union types. Each member of the union is evaluated individually.
type Example<T> = T extends string ? "string" : "other";
type A = Example<string | number>; // "string" | "other"
Conditional Type with Inference
Using infer to extract the element type from an array.
type ElementType<T> = T extends (infer U)[] ? U : T;
type A = ElementType<number[]>; // number
type B = ElementType<string[]>; // string
type C = ElementType<boolean>; // boolean
Conditional Type with Constraints
Using conditional types to create types based on constraints.
type ExtractString<T> = T extends string ? T : never;
type A = ExtractString<string | number | boolean>; // string
Utility Types Built with Conditional Types
Several TypeScript utility types are built using conditional types:
Exclude<T, U>
: Excludes from T those types that are assignable to U.Extract<T, U>
: Extracts from T those types that are assignable to U.NonNullable<T>
: Excludes null and undefined from T.ReturnType<T>
: Extracts the return type of a function type T.InstanceType<T>
: Extracts the instance type of a constructor function type T.
Literal Types
📘 typescriptlang.org > literal types
Literal types in TypeScript allow you to specify exact values for a type. They are useful for defining types that accept only specific values, such as strings, numbers, or booleans.
type SecretToEverything = 42;
let secret: SecretToEverything = 42; // ok
let secret: SecretToEverything = 43; // error
Template Literal Types
📘 typescriptlang.org > template literal types
Template literal types in TypeScript allow you to create new types by concatenating string literals. They are useful for creating types that depend on other types or values.
type Name = `Mr. ${string}`;
let name: Name = `Mr. Smith`; // ok
let name: Name = `Mrs. Smith`; // error
Recursive Types
Recursive types in TypeScript are a way to define a type that references itself. Recursive types are used to define complex data structures, such as trees or linked lists, where a value can contain one or more values of the same type.
Example 1: Tree structure
A common use of recursive types is to define a tree structure where each node can have child nodes of the same type.
interface TreeNode {
value: number;
children?: TreeNode[];
}
// Example of a tree structure
const tree: TreeNode = {
value: 1,
children: [
{
value: 2,
children: [{ value: 4 }, { value: 5 }],
},
{
value: 3,
children: [{ value: 6 }, { value: 7 }],
},
],
};
console.log(tree);
Example 2: Linked list
Another example of recursive types is defining a linked list where each node points to the next node in the list.
interface ListNode<T> {
value: T;
next?: ListNode<T>;
}
// Example of a linked list
const list: ListNode<number> = {
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
},
},
},
};
console.log(list);
Comments
Recent Work
Basalt
basalt.softwareFree desktop AI Chat client, designed for developers and businesses. Unlocks advanced model settings only available in the API. Includes quality of life features like custom syntax highlighting.
BidBear
bidbear.ioBidbear is a report automation tool. It downloads Amazon Seller and Advertising reports, daily, to a private database. It then merges and formats the data into beautiful, on demand, exportable performance reports.