TypeScript provides globally available utility
types that
are useful to manipulate and transform types. One of the types,
Omit,
can be used to define a new type with specific properties removed from an
existing type. It works like this:
type Song = {
album: string
artist: string
title: string
loved: boolean
}
type X = Omit<Song, "title" | "loved">
//
// {
// album: string
// artist: string
// }
A thing I’ve disliked about the built-in Omit type is that providing a
non-existent property to Omit doesn’t result in a compile-time error.
As an example, if we renamed the title
property to name
in the Song type,
the code still compiles successfully.
type Song = {
album: string
artist: string
name: string // renamed
loved: boolean
}
type X = Omit<Song, "title" | "loved">
// compiles successfully though `title` doesn't exist on SongProps
//
// {
// album: string
// artist: string
// name: string
// }
Here’s the stricter version of Omit, called OmitStrict, that I defined at work
in our typeutil package, as a drop-in replacement for Omit:
type OmitStrict<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
Compare this to the original Omit:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
Using keyof T
instead of any
ensures that the specified property is
actually present on the type T which you’re omitting the property from.