Stricter Omit type

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.