I am trying to use a type that has all the properties of one type, but also allows adding dynamic properties of another type (similar to this question).
Types are defined like this:
type Foo = string | string[]
type Bar = { n: number, str?: string }
// A dictionary which only allows Foo values
type FooDict = { [key: string]: Foo | undefined }
// Has all static properties of Bar plus some dynamic Foo properties
type FooBar = FooDict & Bar
and I am expecting to use them like this:
const bar: Bar = { n: 1 }
const fooBar: FooBar = bar
const n: number = fooBar.n
const str: string | undefined = fooBar.str
const foo: Foo | undefined = fooBar['someRandomKey']
Problem is that the second line gives a compile error: "Type 'Bar' is not assignable to type 'FooBar'. Type 'Bar' is not assignable to type 'FooDict'. Property 'n' is incompatible with index signature. Type 'number' is not assignable to type 'Foo | undefined'. TS2322".
I don't see any reason why it couldn't work.
- All the keys of
BarandFooDictare strings, so there is no mismatch. - If using a key of
Bar, we can use the corresponding static property of Bar. - Otherwise, we can use the type from
FooDict, which is eitherFoo(when the property exists) orundefined(when using a key with no value).
As mentioned in the linked question, this works if the dynamic properties are typed as any. But since I only need to set Foo instances into the dynamic properties, I would like to enforce it with the type system. Is this possible?
The short answer is that
FooBarandBarare not compatible sinceFooBarpromises a string based index signature whileBardoes not. (Basically that is what the error message says)If you want to assing
BartoFoobaryou have to provide a respective signature which will basically equal yourFooBartype. AssigningFooBartoBarshould be always possible