接口在用作函数的返回类型时允许额外的属性

Cra*_*zit 5 typescript

当接口通过类型指定为函数的返回时,它似乎接受额外的属性。

例如,如果我有一个名为 的空接口MyInterface、一个函数的类型 :type MyFunction = () => MyInterface;和一个函数const myFunction: MyFunction = () => ({ foo: 'bar' }),它不会引发该foo属性的任何错误。

以下是一些示例:

// No 'age' property
interface Human {
  name: string;
}

const human: Human = {
  name: '',
  age: 0 // Error
}

type HumanCreator = (name: Human['name'], age: number) => Human;

const humanCreator: HumanCreator = (name, age) => ({
  name,
  age // No error. Why?
});

const humanCreatorr: HumanCreator = (name, age): Human => ({
  name,
  age // Error
});

const humanCreatorrr = (): Human => ({
  name: '',
  age: 0 // Error
});
Run Code Online (Sandbox Code Playgroud)

humanCreator为什么当我用它键入变量时HumanCreator不关心是否向返回的对象添加额外的属性?

for*_*d04 6

当接口通过类型指定为函数的返回时,它似乎接受额外的属性。

一般来说,TypeScript 使用结构类型,因此将具有附加属性的对象分配给Human接口是完全可以的。

const lui = {
  name: "Lui",
  age: 40
}

const human: Human = lui // works, 
Run Code Online (Sandbox Code Playgroud)

您可以分配给type 的lui变量,因为它是子类型,因此具有相同/兼容的属性成员。humanHumantypeof lui

此规则的一个例外是对“新创建的对象文字”的过多属性检查,其目的是为开发人员提供帮助并禁止添加额外的属性。这里的一般想法是,当您定义没有其他间接(访问变量等以获取该对象值)的直接对象文字时,您确切地知道您想要什么属性。

多余的属性检查需要在处理新对象文字的变量、属性或函数上立即添加显式类型注释才能工作。否则,对象字面量类型不再算作“新鲜”(其类型已扩展)。让我们检查您的示例来说明这个概念。

const humanCreator: HumanCreator = (name, age) => ({
  name,
  age // No error. Why?
});
Run Code Online (Sandbox Code Playgroud)

您可以将其视为类型兼容函数对 type 变量的赋值HumanCreator。编译器查看函数表达式(name, age) => ({ name, age }),推断参数类型并确保其返回类型与变量类型兼容。事实上 -{name: string; age:number}返回类型可以分配给Human(结构类型)。

const humanCreatorr: HumanCreator = (name, age): Human => ({
  name,
  age // Error
});

const humanCreatorrr = (): Human => ({
  name: '',
  age: 0 // Error
});
Run Code Online (Sandbox Code Playgroud)

这些情况是不同的,因为您立即用返回类型注释函数Human。编译器不需要返回类型的类型推断。tl;dr要启用多余的属性检查,请尽可能接近地注释对象文字的显式类型。

更多链接