A stricter Omit type

In TypeScript you’ll find globally available utility types that are useful to manipulate and transform types in common ways. One of the types, Omit, can be used to remove specified properties from a type. For the uninitiated it works like this:

type SongProps = {
  album: string
  artist: string
  title: string
  loved: boolean
}

type X = Omit<SongProps, "title" | "loved">
//
// {
//   album: string
//   artist: string
// }

But a thing I’ve disliked about the built-in Omit type is that specifying a non-existent property in an Omit call doesn’t result in an error.

As an example, if we renamed the title property to name in the SongProps type, the Omit line still compiles successfully. (You can imagine how this issue would be exacerbated if the SongProps and Omit lines were far away.)

type SongProps = {
  album: string
  artist: string
  name: string // renamed
  loved: boolean
}

type X = Omit<SongProps, "title" | "loved"> 
// compiles successfully, even though `title` doesn't exist on SongProps
//
// {
//   album: string
//   artist: string
//   name: string
// }

For my use cases, I have always preferred that Omit would fail to compile in this scenario instead—in fact the Pick type works this way. So here’s the slightly modified OmitStrict that I tend to define in a typeutil file as a drop-in replacement:

type OmitStrict<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

compared 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.

 
2
Kudos
 
2
Kudos

Now read this

Vim-like cursor keys on a 60% keyboard

I’m using a 60% keyboard, which has 61 keys—the WASD VP3. It doesn’t have dedicated cursor keys, so I set up Fn + hjkl to act as cursor keys. The default mappings use Fn + ijkl as cursor keys. Fn + i: up Fn + k: down Fn + j: left Fn + l:... Continue →