Search code examples
javascripttypescripttypessymbols

Using symbol as object-key type in TypeScript


I'm trying to define an object with a symbol as key-type since MDN says:

A symbol value may be used as an identifier for object properties [...]

But using it as type for the key-property:

type obj = {
    [key: symbol | string]: string
}

results in the following error:

TS1023: An index signature parameter type must be either 'string' or 'number'.

even it can be used as index-type. I'm using the latest typescript version (v3.7.2), related questions I've found:

I've also took a look at the typescript symbol docs but they only show how it's used as value, not as type.

Example:

const obj = {} as {
    [key: number | symbol]: string // Won't work
};

const sym = Symbol('My symbol');
obj[sym] = 'Hi';

Issue on Microsoft/TypeScript

Open feature request


Solution

  • TypeScript 4.4 allows symbols in index signatures:

    type SymbolIndex = {
        [key: symbol | string]: string // works
    }
    
    const sym = Symbol("descr");
    const t1: SymbolIndex = {
        "foo": "bar",
        [Symbol.iterator]: "qux",
        sym: "sym"
    };
    
    // all result in string
    t1.foo 
    t1.sym 
    t1[Symbol.iterator]
    t1["oh"]
    

    Playground

    With older versions, SymbolIndex will trigger an error:

    An index signature parameter type must be either 'string' or 'number'.(1023)

    Alternative

    If you just want an object type with symbols and no index signature, you can already do that today:

    const sym = Symbol() // note const (no let) 
    type O = {
        foo: string
        [Symbol.iterator]: string
        [sym]: number
    }
    
    let o: O = { [sym] : 3, [Symbol.iterator]: "bar", foo: "qux"}
    
    let { [sym]: symVal } = o
    

    Playground