interface Settings {
theme: "light" | "dark";
fontSize: number;
notifications: boolean;
}
function updateSettings(current: Settings, changes: Partial<Settings>): Settings {
return { ...current, ...changes };
}
const updated = updateSettings(
{ theme: "light", fontSize: 14, notifications: true },
{ fontSize: 16 } // only need to pass what changed
);
output
// Partial<Settings> makes all properties optional
Note Partial only operates one level deep. Nested objects keep their original required types. For deep partial, you need a custom recursive type or a library utility.
Partialall optionalpartial updateoptional propertiesupdate function
Required<T>
syntax
type Result = Required<OriginalType>;
example
interface FormFields {
username?: string;
email?: string;
password?: string;
}
// After validation, all fields must be presenttype ValidatedForm = Required<FormFields>;
const validated: ValidatedForm = {
username: "alice",
email: "alice@example.com",
password: "s3cureP@ss",
};
// Missing any field → compile error
output
// Required<T> removes all ? optional markers
Note Required is the inverse of Partial. Like Partial, it only works one level deep. Useful for representing the 'after-validation' state where you know all optional fields have been filled in.
// Readonly<T> marks all top-level properties as readonly
Note Readonly only applies to the top level. frozen.user.name = 'B' would still compile because the nested object is not frozen. For deep immutability, use 'as const' on literals, or build a DeepReadonly recursive type.
Readonlyimmutable typefreeze typereadonly all properties
Pick<T, Keys>
syntax
type Result = Pick<OriginalType, "key1" | "key2">;
// EmployeePreview has only id, name, and department
Note Pick creates a new type with only the specified keys. The keys must actually exist on T — typos cause compile errors. Pick is great for API response shapes where you only need a subset of fields.
Pickselect propertiessubset typepick fieldsinclude only
Omit<T, Keys>
syntax
type Result = Omit<OriginalType, "key1" | "key2">;
example
interface BlogPost {
id: string;
title: string;
body: string;
authorId: string;
createdAt: Date;
}
type CreatePostInput = Omit<BlogPost, "id" | "createdAt">;
const newPost: CreatePostInput = {
title: "Getting Started with TypeScript",
body: "TypeScript adds type safety to JavaScript...",
authorId: "usr_007",
};
output
// CreatePostInput has title, body, authorId (no id or createdAt)
Note Omit does NOT enforce that the keys exist on T — you can omit keys that are not present without error. This is a known gotcha; misspelled keys silently pass. Use a custom StrictOmit if you need safety.
Omitexclude propertiesremove fieldswithout keysomit type
// Record forces every Role to have a Permission entry
Note When Keys is a union of string literals, Record ensures every literal is present — great for exhaustive mappings. Record<string, T> is equivalent to { [key: string]: T } and does not enforce specific keys.
Recordkey value mapdictionary typeobject from unionexhaustive mapping
Exclude & Extract
syntax
type Result = Exclude<UnionType, ExcludedMembers>;
type Result = Extract<UnionType, ExtractedMembers>;
example
type AllEvents = "click" | "scroll" | "keydown" | "keyup" | "resize";
type KeyboardEvents = Extract<AllEvents, "keydown" | "keyup">;
// "keydown" | "keyup"type NonKeyboardEvents = Exclude<AllEvents, "keydown" | "keyup">;
// "click" | "scroll" | "resize"// Works with complex types tootype OnlyStrings = Extract<string | number | boolean, string>;
// string
output
// Exclude removes members; Extract keeps matching members
Note These work on union members, not object properties. To remove properties from an object, use Omit. Exclude and Extract filter which union members match the condition using distributive conditional types under the hood.
ExcludeExtractfilter unionremove from unionkeep matching types
// NonNullable removes null and undefined from a union
Note NonNullable is shorthand for Exclude<T, null | undefined>. It is commonly used after runtime null checks to assert the cleaned-up type. Pairs well with strictNullChecks.
// ReturnType extracts what the function returns; Parameters extracts the argument tuple
Note Both require typeof when used with a concrete function (not a type). For class constructors, use ConstructorParameters<typeof ClassName>. ReturnType is invaluable for inferring types from existing functions without duplicating definitions.
ReturnTypeParametersfunction return typeextract parametersinfer from function
Awaited<T>
syntax
type Result = Awaited<PromiseType>;
example
type PromisedUser = Promise<{ id: string; name: string }>;
type ResolvedUser = Awaited<PromisedUser>;
// { id: string; name: string }// Handles nested promisestype DeepPromise = Promise<Promise<Promise<number>>>;
type DeepResolved = Awaited<DeepPromise>;
// number// Practical: extract resolved type from async functionasyncfunction loadConfig() {
return { apiUrl: "https://api.example.com", timeout: 5000 };
}
type Config = Awaited<ReturnType<typeof loadConfig>>;
output
// Awaited recursively unwraps all layers of Promise
Note Added in TS 4.5. Awaited recursively unwraps nested Promises until it hits a non-Promise type. Before Awaited existed, developers had to write custom recursive unwrap types. Works with any thenable, not just native Promises.
Awaitedunwrap promisepromise result typeasync return typeresolve promise type