Define a type with a subset of an object keys

Issue

I wonder how to create a type that has only a subset of keys from an object, imagine the following object:

const something = {
  cannary: "yellow",
  coyote: "brown",
  fox: "red",
  roses: "white",
  tulipan: "purple",
  palmera: "green"
}

If I defined a type like:

type Something = keyof typeof something

Autocomplete and the check type will work for all the keys, but what about if I want to accept only some of those keys like:

type Animal = keyof typeof {only cannary|coyote|fox} 

is this feasible to do in typescript?

Solution

The built-in Extract<T, U> type is a good candidate for this. It will…

Extract from T those types that are assignable to U

However, in your case, this still allows

Extract<keyof typeof something, 'cannary' | 'coyote' | 'monkey'>

to pass, even though 'monkey' does not exist in T.

A small modification to the Extract<T, U> type from:

type Extract<T, U> = T extends U ? T : never;

to

type ExtractExact<T, U extends T> = T extends U ? T : never;

forces the consumer to supply a type for U that must extend T.

Now:

type CausesTypeError = ExtractExact<keyof typeof something, 'cannary' | 'coyote' | 'monkey'>

will show up immediately in the IDE as something unintended:

enter image description here

Playground Link

Answered By – spender

Answer Checked By – Marie Seifert (AngularFixing Admin)

Leave a Reply

Your email address will not be published.