Welcome, fellow developers, to the captivating world of TypeScript utility types! TypeScript equips us with a toolbox of utility types to simplify complex type manipulations. Let's dive right in, understanding their essence with crisp definitions and insightful examples.
Partial<Type>: Embracing Optionality
With Partial
, all properties of a type become optional, offering flexibility in handling optional data.
interface User {
name: string;
age?: number;
}
function updateUser(user: User, updates: Partial<User>): User {
return { ...user, ...updates };
}
const initialUser: User = { name: "Vroon" };
const updatedUser = updateUser(initialUser, { age: 20 });
Awaited<Type>: Unraveling Promises
The Awaited
type unwraps Promise types, revealing their resolved values.
type AwaitingString = Awaited<Promise<string>>;
// Result: string
type AwaitingNestedPromise = Awaited<Promise<Promise<number>>>;
// Result: number
type AwaitingMixedType = Awaited<boolean | Promise<number>>;
// Result: number | boolean
Readonly<Type>: Safeguarding Immutability
Readonly
ensures that all properties of a type are immutable, preventing unintended modifications.
interface Point {
readonly x: number;
readonly y: number;
}
const origin: Readonly<Point> = { x: 0, y: 0 };
Record<Keys, Type>: Crafting Precise Structures
Record
constructs objects with specified keys and corresponding value types.
type ContactInfo = Record<"email" | "phone", string>;
const contact: ContactInfo = { email: "example@example.com", phone: "+123456789" };
Required<Type>: Makes properties mandatory
Required
constructs a type consisting of all properties of Type set to required.
interface Props {
a?: number;
b?: string;
}
const obj: Props = { a: 5 };
const obj2: Required<Props> = { a: 5 };
// Property 'b' is missing in type '{ a: number; }' but required in type 'Required<Props>'.
Pick<Type, Keys>: Selecting Specific Properties
Pick
extracts specific properties from a type, creating a new tailored type.
interface Car {
make: string;
model: string;
year: number;
}
type CarInfo = Pick<Car, "make" | "year">;
const carDetails: CarInfo = { make: "Toyota", year: 2022 };
Omit<Type, Keys>: Excluding Unwanted Properties
Omit
removes specified properties from a type, producing a refined subset.
interface Book {
title: string;
author: string;
pages: number;
}
type BookPreview = Omit<Book, "pages">;
const preview: BookPreview = { title: "The Great Gatsby", author: "F. Scott Fitzgerald" };
Exclude<UnionType, ExcludedMembers>: Filtering Union Types
Exclude
eliminates members from a union type based on specified exclusions.
type NonNumeric = Exclude<number | string | boolean, number>;
const values: NonNumeric[] = ["apple", true];
Extract<Type, Union>: Retrieving Union Members
Extract
fetches members from a union type based on specified inclusion criteria.
type Numeric = Extract<number | string | boolean, number>;
const nums: Numeric[] = [10, 20];
NonNullable<Type>: Removes null and undefined
NonNullable
constructs a type by excluding null and undefined from Type.
type T0 = NonNullable<string | number | undefined>;
// T0: string | number
Parameters<Type>: Extracts function parameters
Parameters
make a tuple type from the types used in the parameters of a function type Type.
declare function f1(arg: { a: number; b: string }): void;
type T0 = Parameters<() => string>;
// T0: []
type T1 = Parameters<(s: string) => void>;
// T1: [s: string]
type T2 = Parameters<<T>(arg: T) => T>;
// T2: [arg: unknown]
type T3 = Parameters<typeof f1>;
// T3: [arg: { a: number; b: string }]
ConstructorParameters<Type>: Extracts constructor parameters
ConstructorParameters
make a tuple or array type from the types of a constructor function type.
type T0 = ConstructorParameters<ErrorConstructor>;
// T0: [message?: string]
type T1 = ConstructorParameters<FunctionConstructor>;
// T1: string[]
type T2 = ConstructorParameters<RegExpConstructor>;
// T2: [pattern: string | RegExp, flags?: string]
class C {
constructor(a: number, b: string) {}
}
type T3 = ConstructorParameters<typeof C>;
// T3: [a: number, b: string]
ReturnType<Type>: Extracts return type
ReturnType
constructs a type consisting of the return type of function Type.
declare function f1(): { a: number; b: string };
type T0 = ReturnType<() => string>;
// T0: string
type T1 = ReturnType<(s: string) => void>;
// T1: void
type T2 = ReturnType<typeof f1>;
// T2: { a: number; b: string }
InstanceType<Type>: Returns instance type
InstanceType
constructs a type consisting of the instance type of a constructor function in Type.
class C {
x = 0;
y = 0;
}
type T0 = InstanceType<typeof C>;
// T0: C
ThisParameterType<Type>: Extracts 'this' type
ThisParameterType
extracts the type of the this parameter for a function type.
function toHex(this: Number) {
return this.toString(16);
}
function numberToString(n: ThisParameterType<typeof toHex>) {
return toHex.apply(n);
}
OmitThisParameter<Type>: Removes 'this' parameter
OmitThisParameter
removes the this parameter from Type.
function toHex(this: Number) {
return this.toString(16);
}
const fiveToHex: OmitThisParameter<typeof toHex> = toHex.bind(5);
console.log(fiveToHex());
ThisType<Type>: Contextual 'this' marker
ThisType
serves as a marker for a contextual this type.
type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
};
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
let data: object = desc.data || {};
let methods: object = desc.methods || {};
return { ...data, ...methods } as D & M;
}
These examples only scratch the surface of TypeScript utility types. Embrace their versatility, leverage their capabilities, and witness your TypeScript endeavours soar to new heights of clarity and efficiency.
Once you go TypeScript, you never go back ;)
Thank you for reading the article! If you found it helpful, consider giving me a follow on GitHub for more insightful content and updates.