当接口通过类型指定为函数的返回时,它似乎接受额外的属性。
例如,如果我有一个名为 的空接口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不关心是否向返回的对象添加额外的属性?
当接口通过类型指定为函数的返回时,它似乎接受额外的属性。
一般来说,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要启用多余的属性检查,请尽可能接近地注释对象文字的显式类型。
更多链接