Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript - Type is missing the following properties from type even though all options are defined

Tags:

I've got the following Typescript definitions:

type TDisplayKey = "a" | "b" | "c";

const DISPLAY_KEYS: Record<string, TDisplayKey> = {
  A: "a",
  B: "b",
  C: "c"
};

const DISPLAY_KEY_TITLES: Record<TDisplayKey, string> = {
  [DISPLAY_KEYS.A]: "Ay",
  [DISPLAY_KEYS.B]: "Bi",
  [DISPLAY_KEYS.C]: "Ci"
};

And I'm getting the following error on DISPLAY_KEY_TITLES (In VSCode):

Type '{ [x: string]: string; }' is missing the following properties from type 'Record<TDisplayKey, string>': a, b, c

I've clearly defined all three properties. What am I doing wrong?

like image 893
Uri Klar Avatar asked Mar 18 '19 09:03

Uri Klar


1 Answers

The problem is with DISPLAY_KEYS. A property of DISPLAY_KEYS is typed as "a" | "b" | "c". Because of this typescript will not try to be more strict with the computed properties you can define.

You want to make DISPLAY_KEYS more specific. You can manually define the type as:

const DISPLAY_KEYS: {
    A: "a";
    B: "b";
    C: "c";
} = {
  A: "a",
  B: "b",
  C: "c"
}

That is unfortunately a lot of repetition. Another option is to use DISPLAY_KEYS = { /*...*/ } as const (soon to be available in 3.4) or you can use a helper function to help typescript infer the above type:

type TDisplayKey = "a" | "b" | "c";

const DISPLAY_KEYS = (<T extends Record<string, TDisplayKey>>(o:T)=>o)({
    A: "a",
    B: "b",
    C: "c"
});

const DISPLAY_KEY_TITLES: Record<TDisplayKey, string> = {
    [DISPLAY_KEYS.A]: "Ay",
    [DISPLAY_KEYS.B]: "Bi",
    [DISPLAY_KEYS.C]: "Ci"
};
like image 192
Titian Cernicova-Dragomir Avatar answered Nov 15 '22 06:11

Titian Cernicova-Dragomir