Why does TypeScript's Omit not enforce the value of the omitted properties?

1.3k Views Asked by At

Background: (can be skipped)

I was fiddling around to make some update(person: Person) statement more usable by allowing a subset of properties it should update. I was thinking there are 2 options:

  • The id is passed explicitly to the update method as the first argument, and then Partial<Person> or Omit<Person, 'id'> as the 2nd argument.
  • Or, the update method's signature remains as is, with only 1 input arg, and enforces that the id property is in the object provided.

So Omit seems like a good candidate to me, but the keys to omit can be of any string value.

Question:

Why does TypeScript not enforce the value of the keys provided to Omit ? Is there any good use not to which I am overseeing?

See the following code

export interface Person {
  id: string;
  age: number;
  name: string;
}

type UpdatePerson = Omit<Person, 'whatEver'>; // Why does 'whatEver' not cause compile issues?
type UpdatePerson2 = Pick<Person, 'id'> & Partial<Person>; // Great, a valid key is enforced here
type UpdatePerson3 = Pick<Person, 'thisDoesNotCompile'> & Partial<Person>; // This line fails compilation as that property isn't part of the interface

For now I go with update(person: UpdatePerson) and type UpdatePerson = Pick<Person, 'id'> & Partial<Person>;. This makes all properties optional, and the id mandatory.

1

There are 1 best solutions below

0
Jeff Bowman On

In short, this behavior was selected so the built-in Omit could be most compatible with existing DefinitelyTyped libraries. Those libraries were already split on whether Omit should be strict, and picking a looser Omit prevented those existing libraries from breaking at the expense of slightly less compiler safety and autocomplete for code yet to be written.


For background: this was requested in microsoft/TypeScript#30825, with this response from DanielRosenwasser:

It seems like the constrained Omit type is going to make at least half of users unhappy based on declarations within DefinitelyTyped. We've decided to go with the more permissive built-in which your own constraints can build on.

And these from language co-author Ryan Cavanaugh:

I have to clear up this misconception. There were 12 different definitions of Omit on DT and the two most popular definitions differed on whether or not to constraint [sic] the key: [snip]

You can pick at the numbers and try to declare a democratic majority or something, but the reality is that only one definition doesn't break a substantial portion of people.

It is a popular request with duplicates here on SO and on GitHub, and corresponding concise strict equivalents are easy to write/derive and also available in other libraries like type-zoo.