当接口用作函数的返回类型时,它允许附加属性

时间:2019-11-09 16:58:36

标签: 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
});

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

1 个答案:

答案 0 :(得分:2)

  

接口通过类型分配为函数的返回值时,它似乎会接受其他属性。

通常,TypeScript使用structural typing,因此可以将具有附加属性的对象分配给Human接口。

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

const human: Human = lui // works, 

您可以将lui分配给类型为{{1}的变量human,因为Human是子类型,因此具有相同/兼容的属性成员。

此规则的例外是excess property checks的“新创建的对象文字”,旨在作为开发人员的帮助,并禁止添加其他属性。通常的想法是,当您定义一个没有其他间接性的直接对象文字(访问变量等以获取该对象值)时,您便完全知道所需的属性。

多余的属性检查要求在紧跟新对象文字的变量,属性或函数后紧跟显式类型注释,以便起作用。否则,对象文字类型将不再视为“新鲜”(其类型为widened)。让我们检查您的示例以说明概念。

typeof lui

您可以看到这是类型兼容函数对类型为const humanCreator: HumanCreator = (name, age) => ({ name, age // No error. Why? }); 的变量的赋值。编译器查看函数表达式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 }); 返回类型对函数进行注释。编译器不需要返回类型的类型推断。 tl; dr 要启用多余的属性检查,请为对象文字的显式类型尽可能靠近注释。

其他链接