Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why a Typescript Record with a union of a primitive and a specific string makes the string mandatory?

I have this type:

type ErrorMessages = Record<number | 'default', string>;

Then, when I define a variable as const text: ErrorMessages = {403: 'forbidden'}, Typescript says that default is missing in the type:

Playground example

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Why a Typescript Record with a union of a primitive and a specific string makes the string mandatory?

>Solution :

Record distributes the union you give for the key argument, creating an object type requiring all of those keys. In your IDE or the TypeScript playground, if you hover over ErrorMessages, you’ll see the expanded definition of it, which makes the problem clear:

type ErrorMessages = {
    [x: number]: string;
    default: string;
}

Similarly, Reocrd<"a" | "b", string> requires both a and b properties.

Instead, you can define ErrorMessages as an object type directly, explicitly while making default optional via a postfix ?, like this:

type ErrorMessages = {
    [key: number]: string;
    default?: string;
};

That allows both of your assignments:

const text1: ErrorMessages = { 403: "forbidden" };
const text2: ErrorMessages = { default: "something else" };

That will also allow multiple messages, which I think is correct given the type name ErrorMessages (plural):

const text3: ErrorMessages = {
    default: "something else",
    403: "forbidden",
};

…while disallowing other string keys:

// Error as desired
const text4: ErrorMessages = { foo: "bar" };
//                             ^^^^^^^^^^ Type '{ foo: string; }' is not assignable to type 'ErrorMessages'.
//                                        Object literal may only specify known properties, and 'foo' does not exist in type 'ErrorMessages'. (2322)

Playground link

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading