I'd like to define a mapped type where the keys 'foo' and 'bar' are of type number and all other keys are of type string
My first intuition was to solve this with a conditional type like so:
type FooOrBar = 'foo' | 'bar';
type MyMappedType = {
[key in FooOrBar | string]: key extends FooOrBar ? number : string;
}
var x: MyMappedType = {
foo: 1, // Type 'number' is not assignable to type 'string'.(2322)
bar: 2, // Type 'number' is not assignable to type 'string'.(2322)
baz: 'I am a string' // ok!
}
The problem here is that typescript narrows the typealias FooOrBar | string down to type string in the key. So in fact typescript evaluates this type to
type MyMappedType = {
[key in string]: key extends FooOrBar ? number : string;
}
so the condition key extends FooOrBar is always false and the type-definition is useless for my need.
My second intuition was to use an intersection type:
type FooOrBar = 'foo' | 'bar';
type MyMappedType = {
[key in FooOrBar]:number;
} & {
[key in string]: string;
};
var x: MyMappedType = { // Type 'number' is not assignable to type 'string'.(2322)
foo: 1,
bar: 2,
baz: 'I am a string'
}
But this doesn't work either.
Is there any possibility to define a type like this in typescript?