Bug报告
🔎 搜索关键词
不确定哪些关键词适用于此问题。
🕗 版本与回归信息
这种行为在4.7、4.8和4.9.0-dev.20220920中出现。
⏯ Playground链接
查看此处
💻 代码
type Key = 'a' | 'b';
type Values = Record<Key, { value: number }>;
const x: Values = { a: { value: 1 }, b: { value: 2 } };
const key: Key = 'a' as Key; // <= HERE: Without "as Key" it detects the type error
const y: Values = { ...x, [key]: { value: 'oops' } }; // <= OOPS: Wrong type for `value`!
一个变体:
type Key = 'a' | 'b';
type Values = Record<Key, { value: number }>;
const data: Values = { a: { value: 1 }, b: { value: 2 } };
// No error reported, while it returns the wrong type.
const example = (key: Key): Values => ({ ...data, [key]: { value: 'oops' } });
example('a'); // => {"a": {value: "oops"}, "b": {value: 2}}
🙁 实际行为
尽管在代码示例中 key
被输入为 "a" | "b"
,但TypeScript并未检测到我们试图为 value
属性使用错误的类型。
🙂 预期行为
类型应该被推断为 {a: {value: string}} | {b: {value: string}}
,从而导致错误,但实际上任何值都被默默接受,这破坏了类型契约。
4条答案
按热度按时间vlju58qv1#
与 #13948 密切相关
2ledvvac2#
为了明确:问题在于错误类型的代码被默默接受,而不是正确的代码被拒绝。
jpfvwuh43#
这里的问题是我们没有一个类型来表示对象字面量(或者说,没有生成组合爆炸性的方法)。
如果你写了一个类似这样的东西:
那么对于
obj
的唯一精确类型就是具有26 ** 4 = 456976
成分的类型。我们可以尝试计算一个带有可选成员的悲观类型 -
{ a?: number, b?: number, c?: number ... }
。当只有两个可能的键值时,这可能会有点傻,但至少是正确的。tyky79it4#
至少,应该有一个选项可以拒绝故意破坏输入约定的代码,并要求开发者添加某种注解以使其通过。