通用功能允许任意键

Dan*_*Dan 4 typescript

为什么以下代码编译成功?由于bar不是其中的一部分MyState,我希望它会产生编译器错误.

type MyState = { foo: number; };
type Reducer<T> = (state: T) => T;

const wtf: Reducer<MyState> = (state) => {
  return { foo: 123, bar: 123 }; // `bar` isn't part of MyState
};
Run Code Online (Sandbox Code Playgroud)

Rya*_*ugh 5

crashmstr的答案是正确的,但它是值得解释为什么这种情况下,从一个地方你不同的得到一个错误.

在特定情况下,对象文字只会导致额外的属性错误.

在这种情况下:

var x: MyState = { foo: 10, bar: 20 };
Run Code Online (Sandbox Code Playgroud)

类型系统执行以下步骤:

  • 检查MyState是否是有效类型(它是)
  • 检查初始化程序是否有效:
    • 初始化程序的类型是什么?
      • 它是新鲜的对象类型{foo: 10, bar: 20}
    • 可分配给MyState
      • foo房产吗?
      • 它的类型是否匹配?
        • 是(10- > number)
      • 是否有新鲜型的额外属性?
          • 错误

这里的关键是新鲜感.如果对象文字中的类型直接来自对象文字本身,则它是新鲜的.这意味着它们之间存在差异

// Error
var x: MyState = { foo: 10, bar: 20 };
Run Code Online (Sandbox Code Playgroud)

// OK
var x1 = { foo: 10, bar: 20 };
var x2: MyState = x1;
Run Code Online (Sandbox Code Playgroud)

因为对象文字的新鲜度一旦被分配就消失了x1.

你的例子遭受同样的命运 - 一旦它成为函数返回类型的一部分,对象文字的新鲜度就消失了.这也解释了如果在函数表达式上有返回类型注释,则重新出现错误的原因.