Overview
In version 3.5, TypeScript added an Omit<T, K>
helper type to the lib.es5.d.ts type definition file that ships as part of the TypeScript compiler. The Omit<T, K>
type lets us create an object type that omits specific properties from another object type:
|
|
The Omit<T, K>
helper type is defined in lib.es5.d.ts like this:
|
|
To untangle { If you untangle a confused or complicated situation, you make the different things involved clear, or put the situation right } this type definition and understand how it works, let’s see how we could’ve come up with { 提出;想出 } our own version of the Omit<T, K>
helper type ourselves.
Defining the Omit<T, K>
Helper Type
Let’s start with the same User
type we’ve seen above:
|
|
First, we need to be able to retrieve all keys of the User
type. We can use the keyof
operator to retrieve a union of string literal types that contains all property keys of this object type:
|
|
Next, we need to be able to exclude a specific string literal type from a union of string literal types. In the case of our User
type, we want to exclude the type "email"
from the union "id" | "name" | "email"
. We can use the Exclude<T, U>
helper type to do that:
|
|
The Exclude<T, U>
type is defined in lib.es5.d.ts like this:
|
|
It’s using a conditional type and the never
type. Using the Exclude<T, U>
helper type, we’re removing those types in our union type "id" | "name" | "email"
that are assignable to the "email"
type. That is only true for the string literal type "email"
itself, so we’re left with the union type "id | "name"
.
Finally, we need to create an object type that contains a subset of the properties of our User
type. Specifically, we want to create an object type that contains only those properties whose keys are found in the UserKeysWithoutEmail
union type. We can use the Pick<T, K>
helper type to pick those properties off of our User
type:
|
|
Here’s how the Pick<T, K>
helper type is defined within lib.es5.d.ts:
|
|
The Pick<T, K>
type is a mapped type that’s using the keyof
operator and an indexed access type T[P]
to retrieve the type of the property P
in the object type T
.
Now, let’s summarize all the type operations we’ve performed using keyof
, Exclude<T, U>
, and Pick<T, K>
in a single type:
|
|
Notice that this type is specific to our User
type. Let’s make this a generic type so we can reuse it in other places:
|
|
We can now use this type to compute our UserWithoutEmail
type:
|
|
Since object keys can only be strings, numbers, or symbols, we can add a generic constraint to the type parameter K
of our Omit<T, K>
helper type to only allow types string
, number
, or symbol
for keys:
|
|
The generic constraint extends string | number | symbol
is a bit verbose. We can replace the string | number | symbol
union type by the keyof any
type since the two are equivalent:
|
|
And there we go! We’ve arrived at the exact definition of the Omit<T, K>
helper type as it is found within the lib.es5.d.ts type definition file:
|
|
Unrolling Omit<User, "email">
Here’s a step-by-step evaluation of the Omit<User, "email">
type. Try to follow every step to understand how TypeScript is computing the final type:
|
|
Et voilà, our final UserWithoutEmail type.