I'm just starting out with TypeScript and have come across some confusing behavior. If I have an interface MyInterface with multiple properties and a key: keyof MyInterface, I can create a new instance of the interface using an arbitrary value for the key property. Consider the following:
interface Values {
one: 1;
two: 2;
}
function getNewVals(vals: Values, key: keyof Values): Values {
// aValue: 1 | 2, so clearly typescript knows the union of possible values
const aValue = vals[key];
// but this is not an error
return { ...vals, [key]: "foo" };
// I can do this, too
const another: Values = { one: 1, two: 2, [key]: "foo" };
// however, this is an error as expected, since 2 isn't assignable to the one
// property
vals[key] = 2;
}
On the other hand, if my interface has just one property, the error is caught:
interface JustOneValue {
one: 1;
}
function getNewJustOneVal(
vals: JustOneValue,
key: keyof JustOneValue
): JustOneValue {
// this is fine now as expected
vals[key] = 1;
// but the following are both errors:
// "Type of computed property's value is 'string', which is not assignable to type '1'"
return { ...vals, [key]: "foo" };
// "Type of computed property's value is '2', which is not assignable to type '1'"
return { ...vals, [key]: 2 };
}
What is going on here? On the one hand, I would like to be able to say something like return { ...vals, [key]: (value in union of property types) };, even though I'm not sure I should be able to (provided the property types are not identical), since I don't know which key is. But the fact that I can assign anything to key seems wrong. Have I found a bug, or is this explainable?