TYPESCRIPT / CHAPTER 12
Derive API types from one model
AdvancedUse mapped types to prevent duplicated contracts from drifting.
By the end of this chapter
- Derive subsets and optional updates
- Preserve field value types with indexed access
- Recognize what type-level transformations do not execute
The idea
Several related APIs often use different views of one model: a full record, a public subset, and an update request. Deriving those views from the source type reduces duplicated field lists and inconsistent value types. Pick selects properties, Partial makes properties optional, and mapped types apply a transformation across a set of keys. These operations describe contracts; they do not copy or filter runtime objects.
Design the contract around the operation’s authority. An update type should expose only fields that callers may change, rather than blindly applying Partial to a record containing identity or audit fields. Optional updates also require a runtime merge policy for absent and explicitly provided values. Check what emitted code does separately from what the derived type permits at compile time.
type Profile = {id: string; name: string; active: boolean};
type Edit = Partial<Pick<Profile, "name" | "active">>;
function apply(profile: Profile, edit: Edit): Profile {
return {...profile, ...edit};
}
console.log(apply({id: "p1", name: "Ada", active: true}, {name: "Bo"}).name);Bo
The edit type excludes id and makes the allowed fields optional. The spread expression, not the type alias, performs the runtime merge.
Try it yourself
Derive a settings update type that permits only theme and pageSize, leaving accountId outside the update contract.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING