Home > OS >  Typescript: Can someone explain what's the square bracket [P] after {} does?
Typescript: Can someone explain what's the square bracket [P] after {} does?

Time:02-12

I was reading this article about what's new in typescript 4.6 and I came across this weird syntax.

Could someone please explain what it does?

type UnionRecord<P extends keyof TypeMap> = { [K in P]:
    {
        kind: K;
        v: TypeMap[K];
        f: (p: TypeMap[K]) => void;
    }
}[P];

The {}[P] : this [P] followed by the {}. Why is it there?

The full typescript code is given below.

interface TypeMap {
    "number": number;
    "string": string;
    "boolean": boolean;
}

type UnionRecord<P extends keyof TypeMap> = { [K in P]:
    {
        kind: K;
        v: TypeMap[K];
        f: (p: TypeMap[K]) => void;
    }
}[P];

function processRecord<K extends keyof TypeMap>(record: UnionRecord<K>) {
    return record.f(record.v);
}

processRecord({
    kind: "string",
    v: "hello!",

    // 'val' used to implicitly have the type 'string | number | boolean',
    // but now is correctly inferred to just 'string'.
    f: val => {
        console.log(val.toUpperCase());
    }
})

CodePudding user response:

Without the [P] you'd get a map with keys from P, in this example this would be a map with a subset of the keys "number", "string" and "boolean".

By adding an index lookup with the entire set of keys P this instead evaluates to a union type of all possible values for the given keys or explicit: Inter["number"] | Inter["string"] | Inter["boolean"] where

type Inter<P extends keyof TypeMap> = {
    [K in P]: {
        kind: K;
        v: TypeMap[K];
        f: (p: TypeMap[K]) => void;
    }
}

For another example consider:

interface User {
  firstName: string;
  lastName: string;
  active: boolean;
}

type UserFieldTypes = User[keyof User]
// UserFieldTypes is User['fistName'] | User['lastName'] | User['active']
// which equals string | string | boolean

Feel free to ask when there's still something unclear to you.

  • Related