Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Consider using a mapped object type instead." - what's a mapped object type and how do I use it here?

Tags:

typescript

When I try to compile this Typescript code

interface Foo { 
    [foo: "hello" | "world"]: string;
}

I get this error message

An index signature parameter type cannot be a union type. Consider using a mapped object type instead.

What is a mapped object type, and how do I use it?

like image 898
Daniel Rosenwasser Avatar asked Aug 02 '18 17:08

Daniel Rosenwasser


People also ask

What is a mapped object?

A mapping object maps values of one type (the key type) to arbitrary objects. Mappings are mutable objects. There is currently only one mapping type, the dictionary . A dictionary's keys are almost arbitrary values.


2 Answers

A mapped object type operates on a set of singleton types and produces a new object type where each of those singletons is turned into a property name.

For example, this:

type Foo = {
    [K in "hello" | "world"]: string
};

would be equivalent to

type Foo = {
    "hello": string;
    "world": string;
};

Keep in mind that a mapped object type is a distinct type operator - that syntax in the braces can't be used in interfaces, or object types with other members. For example

interface Foo {
    [K in "hello" | "world"]: string; // ❌
}

produces the following error:

A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.

Mapped object types are useful for a lot of different things. Read more here: https://www.typescriptlang.org/docs/handbook/2/mapped-types.html

like image 72
Daniel Rosenwasser Avatar answered Nov 09 '22 19:11

Daniel Rosenwasser


This is invalid:

    type DirectiveType = 'package-as' | 'externals' | 'move-folders' | 'ignore';
    type Directives = { [key:DirectiveType]?: RootDirectives };
    
    export class PkgmetaFile {
        private _directives: Directives = {};
    }

But this is valid:

    type DirectiveType = 'package-as' | 'externals' | 'move-folders' | 'ignore';
    type Directives = { [Key in DirectiveType as string]?: RootDirectives };
    
    export class PkgmetaFile {
        private _directives: Directives = {};
    }
like image 11
ChrisKader Avatar answered Nov 09 '22 19:11

ChrisKader