Skip to main content

Partial and Required

Another common scenario when working with objects is needing the exact same shape, but with different strictness regarding which fields must be present.

Partial

Partial<Type> takes an existing type and makes all of its properties optional (?).

This is most commonly used in state management or when writing update functions. When patching a database record, you rarely send the entire object; you only send the fields that changed.

interface Product {
id: number;
name: string;
price: number;
inStock: boolean;
}

// All fields become optional: id?, name?, price?, inStock?
function updateProduct(id: number, updates: Partial<Product>) {
// Database update logic
}

updateProduct(1, { price: 99 }); // Valid, we only updated the price

Required

Required<Type> is the opposite. It takes an existing type and makes all of its properties strictly required, removing any optional ? modifiers.

This is extremely useful when merging user-provided configuration objects with a set of default values.

interface Config {
retries?: number;
timeoutMs?: number;
}

// User only provides some options
const userConfig: Config = { retries: 3 };

// After merging with defaults, everything is guaranteed to be present
const finalConfig: Required<Config> = {
retries: userConfig.retries ?? 1,
timeoutMs: userConfig.timeoutMs ?? 5000,
};

// => finalConfig.timeoutMs is strictly a number, not number | undefined

Shallow vs Deep

A critical sharp edge: Partial and Required are shallow. They only affect the top level of the object. If you have nested objects, their properties remain unchanged.

interface Settings {
theme: string;
network: {
host: string;
port: number;
};
}

type PartialSettings = Partial<Settings>;
// => { theme?: string, network?: { host: string; port: number } }
// Note that network itself is optional, but IF you provide it, you must provide both host and port.

To make nested properties optional, you would need a custom recursive type, often called DeepPartial.

Use Partial for updates and Required for normalized defaults. Both utilities are shallow and only affect the first level of properties.