Home > Mobile >  About the in operator of TypeScript
About the in operator of TypeScript

Time:01-19

In the TypeScript documentation site

https://www.typescriptlang.org/docs/handbook/2/mapped-types.html

it has sample code as follows:

type EventConfig<Events extends { kind: string }> = {
    [E in Events as E["kind"]]: (event: E) => void;
}
 
type SquareEvent = { kind: "square", x: number, y: number };
type CircleEvent = { kind: "circle", radius: number };
 
type Config = EventConfig<SquareEvent | CircleEvent>

what's the meaning of E in Events?

Please help me! Thank you very much!

CodePudding user response:

The in keyword is used for a few different things in TypeScript, but this particular one is using in to select each individual member of the union type Events in order to map it.

EventConfig is a mapped type that uses the members of the union to define the properties of an object type. (We know that because of the form it's in, { KeyType: ValueType }.) E in Events defines the E identifier, saying "for each union member, use E to refer to that individual member's type" for the purposes of defining each property in the object type being defined. Given the example EventConfig<SquareEvent | CircleEvent>, that means that E is each individual member of the union (SquareEvent and, separately, CircleEvent) during the mapping operation (in contrast, Events is the union of those members). It's almost like a loop through the union members (though it isn't a loop).

After E in Events, the as E["kind"] part of the property key expression says "And from E, take the type of the kind property as the property key."

With that in mind, let's look at the overall property definition part of that mapped type:

{
    [E in Events as E["kind"]]: (event: E) => void;
}

For EventConfig<SquareEvent | CircleEvent>, that will be evaluated with E being SquareEvent and also E being CircleEvent, where each of them defines one property in the resulting object type. Let's expand that, replacing E with each of the union members:

{
    [SquareEvent["kind"]]: (event: SquareEvent) => void;
    [CircleEvent["kind"]]: (event: CircleEvent) => void;
}

we can go further, though, because we can resolve the type of SquareEvent["kind"] to the string literal type "square" and CircleEvent["kind"] to "circle", giving us:

{
    square: (event: SquareEvent) => void;
    circle: (event: CircleEvent) => void;
}
  • Related