Partial & Required
Partial makes everything optional, Required makes everything mandatory.
Utility types are TypeScript's built-in JUGAAD tools — they take an existing type and TRANSFORM it into a new one without you rewriting everything from scratch. Think of them as quick modifications you make to an existing setup to suit your current need, no need to build a whole new structure. Partial<T> makes ALL properties optional. Required<T> makes ALL properties required. They are the ultimate time-savers in any large TypeScript codebase.
The analogy is the Hyderabadi jugaad of modifying your order. When the waiter comes to take your order at an Irani cafe, the FULL MENU is the original type — every item has a name, price, and category. But when you say "bhai, mere liye kuch bhi bana do, jo bhi available hai" — that's Partial. You don't demand every single item; whatever is available, you'll take. Some items might be there, some might not — all optional!
But Required is the exact opposite — the caterer at a Hyderabadi wedding says "EVERY item on the contract MUST be served. No skipping the double ka meetha!" Every property becomes mandatory, no excuses, no compromises. Partial = "jo mile woh theek hai." Required = "sab kuch chahiye, bhai, koi kami nahi!" These two utility types form the foundation of TypeScript's type transformation system, and once you understand them, a whole world of type manipulation opens up.
Partial<T> takes a type T and makes every property optional by adding ? to each one. It's the most commonly used utility type in TypeScript because the "update" pattern is so universal in application development.
The Mechanics:
interface User {
name: string;
age: number;
email: string;
}
type PartialUser = Partial<User>;
// Result:
// {
// name?: string;
// age?: number;
// email?: string;
// }
You can pass an EMPTY object: const empty: Partial<User> = {} — valid! Or a partial object: const nameOnly: Partial<User> = { name: "Imran" } — also valid!
Real-World Use Case — Update Functions:
function updateUser(
user: User,
updates: Partial<User>
): User {
return { ...user, ...updates };
}
// Only pass what you want to change!
updateUser(existingUser, { age: 26 });
No need to pass the entire object — just the fields you want to update. This is the #1 reason Partial exists.
Implementation — Mapped Type:
type Partial<T> = {
[K in keyof T]?: T[K];
};
It iterates over every key and adds the ? modifier. Note: Partial<User> does NOT make nested objects partial. If User has address: { city: string; pin: number }, the address itself becomes optional, but if provided, city and pin are still required. For deep partial, you need a custom DeepPartial<T>.
Required<T> is the exact opposite of Partial — it makes every property REQUIRED, removing all ? modifiers. It's TypeScript's way of saying "no more maybe, everything is definite now." This is incredibly useful when you've been working with optional configurations and need to guarantee that all fields have been filled before proceeding.
The Mechanics:
interface Config {
host: string;
port?: number;
debug?: boolean;
}
type StrictConfig = Required<Config>;
// Result:
// {
// host: string;
// port: number;
// debug: boolean;
// }
// ERROR! port and debug missing!
const c: StrictConfig = {
host: "localhost"
};
Real-World Use Case — Validated Config:
function createConfig(
input: Config
): Required<Config> {
if (
input.port === undefined ||
input.debug === undefined
) {
throw new Error("Missing!");
}
return input as Required<Config>;
}
After validation, you can safely treat the config as having all fields filled. No more undefined checks needed downstream!
Implementation — Modifier Removal:
type Required<T> = {
[K in keyof T]-?: T[K];
};
The -? is the key — it REMOVES the optional modifier. The - is the modifier removal operator in TypeScript mapped types. Required on an already-required type is a no-op: Required<{ name: string }> is still { name: string }. No harm in using it defensively.
Partial and Required are straightforward in concept, but they come with traps that can bite you in production code. Knowing these will save you from subtle bugs and confusing type errors. Let's walk through the most common ones that catch developers off guard.
Trap 1: Partial doesn't do DEEP partial
interface User {
address: {
city: string;
pin: number;
};
}
type P = Partial<User>;
// address? becomes optional,
// but address.city is STILL required!
You need a recursive DeepPartial for nested optionality:
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object
? DeepPartial<T[K]>
: T[K];
};
Trap 2: Partial doesn't allow excess properties
const p: Partial<User> = {
name: "Imran",
foo: "bar" // ERROR!
};
Partial only makes EXISTING properties optional. It doesn't open the floodgates to any random property. Excess property checking still applies!
Trap 3: Required doesn't validate at runtime
const input: Config = { host: "local" };
// NO runtime check happens!
const strict = input as Required<Config>;
// strict.port is number at compile time,
// but undefined at runtime! Danger!
Required<Config> doesn't magically check if values exist. It's purely a type-level transformation. You still need runtime checks to ensure the data actually exists.
Trap 4: Mutating with Partial — Object.assign(existing, updates) works at runtime, but TypeScript doesn't automatically update existing's type. The merge result should be explicitly typed to be safe.
Here's your complete cheatsheet for Partial and Required. Pin this to your mental whiteboard — these two utility types are the foundation of TypeScript's type transformation system and you'll use them constantly.
Partial<T> — All Properties Optional:
type Partial<T> = {
[K in keyof T]?: T[K];
};
// Use: Update/patch functions
function update(
item: T,
patch: Partial<T>
): T { ... }
Required<T> — All Properties Required:
type Required<T> = {
[K in keyof T]-?: T[K];
};
// Use: Post-validation guarantee
function finalize(
data: T
): Required<T> { ... }
Modifier Operators:
+?adds optional (default in Partial)-?removes optional (used in Required)
Key Rules:
- Partial = "jo mile woh theek hai" — loosens the type
- Required = "sab kuch chahiye" — tightens the type
- Neither does deep/nested transformation by default
- Neither validates at runtime — type-level only!
- Both are zero-cost at runtime (erased during compilation)
The Golden Rule: Partial and Required are the jugaad tools — Partial loosens the bolts, Required tightens them. Use Partial for updates, Required for validation. But remember bhai, deep jugaad needs a custom tool!
Key Points
- Partial
makes all properties optional — perfect for update/patch functions - Required
makes all properties required — perfect for post-validation guarantees - Partial is implemented with +? modifier, Required with -? modifier
- Neither Partial nor Required applies deeply to nested objects by default
- Both are type-level only — no runtime validation or cost
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login