Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In TypeScript, what do "extends keyof" and "in keyof" mean?

In TypeScript, some types are defined using extends keyof or in keyof. I have tried to understand what they mean, but so far I didn't succeed.

What I got is that keyof alone returns a union type which has all the names as possible values that are existent as property names on the type that you specify after keyof.

type T = keyof string; 

T therefor is equivalent to startsWith | endsWith | trim | substring | ....

Is this correct?

Now, if I try to think about what extends keyof and in keyof mean, my gut feeling says the following:

  • extends keyof is any type that derives from T, i.e. it has all these possible values, but maybe more.
  • in keyof is any type that takes values from T, but not necessarily all of them (it's possible, but maybe less).

So, from this POV extends keyof would describe a >= relation, in keyof would describe a <= relation. Is this correct? If not, what would be correct?

like image 946
Golo Roden Avatar asked Aug 03 '19 10:08

Golo Roden


People also ask

What is Keyof TypeScript?

keyof is a keyword in TypeScript which is used to extract the key type from an object type.

What does Keyof Typeof do?

keyof typeof will infer the type of a javascript object and return a type that is the union of its keys. Because it can infer the exact value of the keys it can return a union of their literal types instead of just returning "string".

What does ?: Mean in TypeScript?

What does ?: mean in TypeScript? Using a question mark followed by a colon ( ?: ) means a property is optional. That said, a property can either have a value based on the type defined or its value can be undefined .


1 Answers

For any type T, keyof T is the union of known, public property names of T.

Example:

interface Person {   age: number;   name: string; }  type PersonKeys = keyof Person; // "age" | "name" 

Your assumption that keyof string yields startsWith | endsWith | trim | ... is therefore correct. You can learn more about it in the lookup type release notes.

extends keyof

extends, in this case, is used to constrain the type of a generic parameter. Example:

<T, K extends keyof T>

K can therefor only be a public property name of T. It has nothing to do with extending a type or inheritance, contrary to extending interfaces.

A usage of extends keyof could be the following:

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {   return obj[key]; }  const person: Person = {   age: 22,   name: "Tobias", };  // name is a property of person // --> no error const name = getProperty(person, "name");  // gender is not a property of person // --> error const gender = getProperty(person, "gender"); 

Aside from the documentation on index types, I found this helpful article.

in keyof

in is used when we're defining an index signature that we want to type with a union of string, number or symbol literals. In combination with keyof we can use it to create a so called mapped type, which re-maps all properties of the original type.

A usage of in keyof could be the following:

type Optional<T> = {    [K in keyof T]?: T[K]  };  const person: Optional<Person> = {   name: "Tobias"   // notice how I do not have to specify an age,    // since age's type is now mapped from 'number' to 'number?'    // and therefore becomes optional }; 

Aside from the documentation on mapped types, I once again found this helpful article.

Fun fact: The Optional<T> type we've just built has the same signature as the official Partial<T> utility type!

like image 183
Tobias Tengler Avatar answered Oct 13 '22 00:10

Tobias Tengler