Description
Bug Report
🔎 Search Terms
keyof arbitrary (value | type)
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
keyof
. In particular, I tried on nightly using the playground as suggested.
⏯ Playground Link
Playground link with relevant code
💻 Code
/**********************
* This is the abberant behavior. In getNewVals, I can use key to
* create a new value of any type I wish, and typescript doesn't
* complain.
*/
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;
}
/**********************
* However, when the interface in question has only one value,
* the error is caught as expected.
*/
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 };
}
🙁 Actual behavior
A variable key: keyof MyInterface
can be used to create a new instance of MyInterface
with values of arbitrary types not included in the interface. This is true unless MyInterface
only has one property, in which case the error is reported.
🙂 Expected behavior
The error described above should be caught regardless of the shape of the interface.
I am rather new to TypeScript, and one thing is unclear to me: In reference to the code above, I would like to be able to say something like return { ...vals, [key]: (value in union of property types) };
(this is distinct from what I did say above, which is return { ...vals, [key]: (value NOT in union of property types) };
). However, it isn't clear that I should be able to, provided all property types aren't identical, since I don't know which property key
corresponds to. Clarification on that point, i.e. "What should I be expecting, anyway?", would be greatly appreciated.