Skip to main content

Custom Utility Types in TypeScript (Live Playground)

In this tutorial, we will explore creating custom utility types in TypeScript. Understanding how to create custom utility types will help you write more flexible and type-safe code.

Custom utility types are user-defined generic types that can be used to perform common operations on types, similar to built-in utility types like Partial and Readonly.

Deep Readonly

The DeepReadonly utility type creates a new type with all the properties of the original type set as readonly, recursively:

TypeScript
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};

interface Person {
name: string;
details: {
age: number;
address: string;
};
}

type ReadonlyPerson = DeepReadonly<Person>;

const readonlyPerson: ReadonlyPerson = {
name: 'John Doe',
details: { age: 30, address: '123 Main St' },
};

readonlyPerson.details.age = 31; // Error: Cannot assign to 'age' because it is a read-only property
Live Playground, Try it Yourself

Required Properties

The RequiredProperties utility type creates a new type with the specified properties of the original type set as required:

TypeScript
type RequiredProperties<T, K extends keyof T> = Required<Pick<T, K>> & Omit<T, K>;

interface Person {
name: string;
age?: number;
address?: string;
}

type PersonWithName = RequiredProperties<Person, 'name'>;

const personWithName: PersonWithName = { name: 'John Doe' };
Live Playground, Try it Yourself

NonEmptyArray

The NonEmptyArray utility type creates a new type that ensures an array has at least one element:

TypeScript
type NonEmptyArray<T> = [T, ...T[]];

const validArray: NonEmptyArray<number> = [1, 2, 3];
const invalidArray: NonEmptyArray<number> = []; // Error: Type '[]' is not assignable to type 'NonEmptyArray<number>'
Live Playground, Try it Yourself

Conclusion

In this tutorial, we have explored creating custom utility types in TypeScript. Understanding how to create custom utility types effectively will enable you to create more flexible and type-safe code.