Changdae Park
Changdae Park

Reputation: 1079

How does keyof typeof generic constraint work?

What does "keyof typeof" mean in TypeScript?

I found the above question where the writer asked exactly the same thing I want to ask, but no answer has found the point of the question.

Let's say there is this generic method and a class.

function fn<K extends keyof typeof A>(key: K) ...

class A {
    static a;
    static b;
}

My reasoning is:

  1. typeof keyword returns a string that shows one of the js basic types.

  2. So no matter what the value is, the return type is string.

  3. So keyof "..." should be the indices and "length" and stuff that the string literal can have. In this case, keyof "function" should return type "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "length".

  4. But the actual behavior is that typeof class A returns the constructor.

How could this happen?

Upvotes: 1

Views: 926

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370729

typeof keyword returns a string that shows one of the js basic types.

This is true for JavaScript, but in Typescript, typeof can mean multiple things, depending on the context. Unlike in JS, in TS, when typeof is in a context where a type is expected, typeof expression will evaluate to the (TypeScript-determined) type of expression. For example:

let num = 5;
type Num = typeof num;

results in the Num type being number. This is not the string 'number' - it is the TypeScript Type number.

So, in your code:

function fn<K extends keyof typeof A>(key: K) ...

Since K extends keyof ... is a type context (which is useful for configuring TypeScript's interpretation of the code, but does not exist in the emitted JavaScript), the following typeof indicates to TypeScript to substitute typeof A with the TypeScript-detected type that A is.

In contrast, when not in a type context:

let someStr = 'foo';
const theType = typeof someStr;

Here, typeof is being used in runtime JavaScript, in the emitted code, rather than as TypeScript-specific syntax, so it results in theType being assigned the value 'string' at runtime.

The two ways that typeof can be used are entirely different.

Upvotes: 5

Related Questions