Partial Utility Type in TypeScript
Partial<T> makes every property of a type optional. Use it to describe update payloads, configuration overrides, and any object where only some fields change.
The TypeScript Partial utility type takes an object type and makes every property optional. You pass it a type, and it returns a new type where none of the fields are required. It is the built-in way to say "this object might have any subset of these properties."
The most common use is typing an update function. You have a User type with many required fields. When a user edits their profile, they might only change their email. Partial<User> describes exactly that: an object that looks like User, but where every field is optional.
interface User {
name: string;
email: string;
age: number;
}
function updateUser(user: User, fields: Partial<User>) {
return { ...user, ...fields };
}The fields parameter accepts any subset of User properties. You can pass only the fields that changed and skip the rest. Here is a call that only updates the email:
const original = { name: "Ada", email: "ada@example.com", age: 30 };
const result = updateUser(original, { email: "new@example.com" });
console.log(result);
// Output:
// { name: "Ada", email: "new@example.com", age: 30 }The second argument only provides email. The other properties stay as they were. Without Partial<User>, the compiler would demand that you pass name and age too, even though the update logic does not need them.
What Partial produces
Partial<T> adds a question mark to every property in T. The transformation is straightforward: each field that was required becomes optional.
interface Product {
title: string;
price: number;
inStock: boolean;
}
type PartialProduct = Partial<Product>;After this transformation, PartialProduct is equivalent to writing { title?: string; price?: number; inStock?: boolean } by hand. Every property is now optional.
This means you can pass an object with any subset of Product fields, including an empty object. The compiler will not complain about missing properties. It also means undefined is a valid value.
If you need to distinguish between "not provided" and "explicitly set to undefined", Partial alone is not enough. You would need a different type for that distinction.
Using Partial for configuration defaults
Another strong use case is configuration objects. Define a full AppConfig type that lists every setting, then let callers pass a Partial<AppConfig> to override only the values they care about.
interface AppConfig {
theme: string;
fontSize: number;
showSidebar: boolean;
}
const defaults: AppConfig = {
theme: "light",
fontSize: 16,
showSidebar: true,
};The defaults object represents the full configuration with every field filled in. A setup function accepts a Partial version of AppConfig and spreads the overrides on top of those defaults, so only the fields a caller provides get changed.
function initApp(overrides: Partial<AppConfig>) {
const config = { ...defaults, ...overrides };
console.log(config);
}
initApp({ theme: "dark" });
// Output:
// { theme: "dark", fontSize: 16, showSidebar: true }The caller only specifies the theme. Everything else falls back to the default. This pattern is common in libraries, frameworks, and any code that accepts user-provided options.
Partial is shallow
Partial only affects the top-level properties. If your type has nested object properties, the nested fields stay required.
interface BlogPost {
title: string;
author: { name: string; email: string };
}When you write Partial<BlogPost>, the author property itself becomes optional. But if you do provide an author object, it must still have both name and email. Here is what fails:
type PartialPost = Partial<BlogPost>;
// Error: 'email' is missing inside author
const post: PartialPost = {
author: { name: "Ada" },
};
// Output:
// Property 'email' is missing in type '{ name: string; }'
// but required in type '{ name: string; email: string; }'.Partial made author optional, but once you provide it, the nested type is unchanged. If you need every nested property to become optional, you write a recursive mapped type. That is a more advanced pattern covered in mapped types in TypeScript.
Combining Partial with Pick
Sometimes you only want to make specific properties optional, not the entire type. Combine Partial with Pick utility type in TypeScript to target a subset of fields.
interface User {
id: number;
name: string;
email: string;
age: number;
}
type EditableUserFields = Partial<Pick<User, "name" | "email">>;Here Pick<User, "name" | "email"> selects only name and email. Then Partial makes those two fields optional. The id and age fields are excluded entirely from EditableUserFields, so they can never be changed through a function that uses this type.
The spread merge pattern
The spread operator with Partial is a clean way to produce an updated object. The original stays unchanged, and the function returns a new object:
function edit<T>(original: T, changes: Partial<T>): T {
return { ...original, ...changes };
}The generic T captures the full type of the original. The Partial parameter lets the caller pass only the fields that changed. Here is a call:
const todo = { title: "Buy milk", done: false, priority: 2 } as const;
const updated = edit(todo, { done: true });
console.log(updated);
// Output:
// { title: "Buy milk", done: true, priority: 2 }The return type is the same as the original, so you get full type safety on the result. No type information is lost.
Common mistakes
Expecting Partial to work deeply. It does not. Nested objects keep their required fields. If you need deeply optional types, write a recursive mapped type or restructure your data to avoid deeply nested updates.
Using Partial when only a few properties should be optional. Not every function that accepts partial data needs the entire type to be optional. If only email is updatable, use { email?: string } directly or Partial<Pick<User, "email">>. Being precise about which fields are optional makes the intent clearer.
Confusing Partial with a runtime check. Partial is a compile-time type. It does not validate the shape of data at runtime. If you receive data from an API, you still need runtime validation in TypeScript to verify the actual values.
Rune AI
Key Insights
⚠ This article has a formatting issue and may not display correctly.
Our team has been notified. The content is shown as plain text below.
Frequently Asked Questions
Does Partial work on nested object properties?
What is the difference between Partial and making properties optional with a question mark?
Can Partial be combined with other utility types?
Conclusion
⚠ This article has a formatting issue and may not display correctly.
Our team has been notified. The content is shown as plain text below.
More in this topic
TypeScript Compiler Explained
The TypeScript compiler (tsc) turns .ts files into .js files while checking types. Learn what it does, how to use it, and how it fits your workflow.
Set Up ESLint for TypeScript
Install and configure ESLint with typescript-eslint to catch bugs and enforce consistent code style in your TypeScript project.
Pick Utility Type in TypeScript
Pick creates a new type by selecting only the properties you name from an existing type. Use it to build focused types for specific views, API responses, or function parameters.