Modification
After some thought, I devised an alternative resolution (more like a workaround) that involves extending the types using Mapped Types. It's unfortunate that combining string
and number
still poses challenges. Nevertheless, you can specify the type as string
or any other desired value, then extend it with any
.
interface Foo {
[index: string]: string;
}
type Bar<T extends Foo> = { [P in keyof Foo]: Foo[keyof Foo] | T[keyof T] };
const bar: Bar<{ [index: string]: any }> = {
someProperty: "1",
anotherProperty: 2,
};
I realize your request was for a Type
Generic
that extends Foo
. However, I found a solution without utilizing that approach. If you are willing to make a compromise, here is an alternative:
interface Foo {
[index: string]: number;
}
type Bar<T> = { [index: string]: Foo[keyof Foo] | T[keyof T] };
const bar: Bar<{ someProperty: string }> = {
someProperty: "1",
anotherProperty: 2,
};
In essence, I refined your Foo
interface to only allow property value types of
Foo[keyof Foo]
-> In the provided example, number
, and
T[keyof T]
-> In the given scenario, string
(due to { someProperty: string }
)
utilizing keyof
.
To sum up, the property value types of the bar
-object are now restricted to be either string
or number
(specifically
number | T[keyof T]</code) without explicitly coding the types as <code>string | number
in
Foo
.
Here's another illustration involving boolean
:
interface Foo {
[index: string]: number;
}
type Bar<T> = { [index: string]: Foo[keyof Foo] | T[keyof T] };
const bar: Bar<{ someProperty: boolean }> = {
someProperty: "1", // error!
// ~~~~~~~~~> Type 'string' is not assignable to type 'number | boolean'. ts(2322)
anotherProperty: 2,
};
It's worth noting that dynamically setting a type for the index signature isn't currently feasible, as demonstrated below:
interface Foo {
[index: string]: number;
}
type Bar<T> = { [index: keyof Foo]: ... };
For more information, refer to this issue/suggestion:
https://github.com/microsoft/TypeScript/issues/1778
Hence, mixing string
key type and number
key type proves to be quite challenging.
interface Foo {
[index: number]: number;
}
type Bar<T> = { [index: number]: Foo[keyof Foo] | T[keyof T] };
const bar: Bar<{ 0: string }> = {
0: "1", // error!
//~> Type 'string' is not assignable to type 'number'.ts(2322)
anotherProperty: 2,
};