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

A guide to using built-in TLS in Redis

Redis version 6 added TLS as a built-in feature. This makes me super happy, because I’m now able to use Redis as a store with my applications running on App Engine considering that the traffic is encrypted, without additional tools or a... Continue →