TypeScript - How to represent an index signature as a generic type
Asked Answered
F

2

19

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 })
Flung answered 10/2, 2017 at 9:25 Comment(1)
There is an issue on the TypeScript repo about that: github.com/Microsoft/TypeScript/issues/13398 Guess it is not possible yet.Satori
C
6

cool question!
I think the reason is that this is really an edge case for the compiler that has not been implemented probably because its not worth the effort.

index property keys can only be numbers that is obvious and object property keys can only be string or numbers. So at the end your constraint only states what is fact anyways and what would need to be handled by the compiler via a special case.
So again I assume that Saint Anders ditched that effort ;-)

but why not do this

type StrIndex<TValue> = {
    [key: string]: TValue
}

type NumIndex<TValue> = {
    [key: number]: TValue
}

foo(obj: StrIndex<Bar>)
foo(obj: StrIndex<Bar> & Fooable<string>)

It is not as neat as your solution but as a compromise it seems OK specifically as the set of XXXIndex types is limited to 2

Claudication answered 10/2, 2017 at 10:12 Comment(0)
S
2

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

Squarrose answered 2/2, 2022 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.