'TypeScript - How to represent an index signature as a generic type

Index signatures in TypeScript are defined thus:

Dictionary

[key: string]: T

Array

[index: number]: T

These could be wrapped into some simple, reusable types:

type DictionaryIndex<T> = {
    [key: string]: T
}

type ArrayIndex<T> = {
    [index: number]: T
}

Now I want to wrap these into a single type. I tried this:

type Index<TKey extends string|number, TValue> = {
    [key: TKey]: TValue
}

This does not compile due to the following error:

An index signature parameter must be of type 'string' or 'number'.

Is this not possible?

What the hell for?

Because

foo(obj: Index<string, Bar>)
foo(obj: Index<string, Bar> & Fooable<string>)

looks neater than

foo(obj: { [key: string]: Bar })
foo(obj: { [key: string]: Bar, canFoo: (foo: string) => Bar })


Solution 1:[1]

One alternative solution is to use the Record utility.

foo(obj: Record<string, Bar>)

https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David Nuñez