Why do interfaces with only one property behave differently than those with multiple properties?

Viewed 58

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?

1 Answers

This appears to be a bug after all. I've filed an issue to address it, which has since been marked as a duplicate of another issue from 2017. The reasons why aren't completely clear, but the bug appears to be unactionable at this time.

Related