Imagine, that I have class Foo with string identifier.
class Foo {
id = '123' as FooId;
}
I try to ensure static typing of it using a brand enum.
enum FooIdBranding {}
type FooId = string & FooIdBranding;
So now, my goal is specific object, where the key is FooId
and the value is Foo
.
type fooCache = { [key: FooId]: Foo };
Unfortunately, it doesn't work:
TS1023: An index signature parameter type must be 'string' or 'number'
I thought, that the Record is my solution, but is doesn't work too.
type FooCache = Record<FooId, Foo>;
({} as FooCache)['123' as FooId] = new Foo();
TS 7017: Element implicitly has an 'any' type because type
Record<FooId, Foo>
has no index signature
Is there a correct way in TypeScript to resolve this problem?
"Symbol and Template String Pattern Index Signatures" were added to TypeScript 4.4, so this is now possible.
type FooId = string & {brand: 'FooId'};
const id1 = '1' as FooId
const id2 = '2' as FooId
class Foo {
constructor(public id: FooId) {}
}
type fooCache = { [key: FooId]: Foo };
const foo: fooCache = {
// Type '{ key: Foo; }' is not assignable to type 'fooCache'.
// Object literal may only specify known properties, and 'key' does not exist in type 'fooCache'.(2322)
// (property) key: Foo
key: new Foo(id1)
}
// All good
const bar: fooCache = {
[id1]: new Foo(id1)
}
Example in the TS playground.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With