【问题标题】:For Typed Functions, with return Interface, is allowed to have non Interface's properties对于带返回接口的类型函数,允许具有非接口的属性
【发布时间】:2020-10-15 22:20:22
【问题描述】:

想象一下这个界面:

interface IUser { 
  id: string;
  name: string;
  age: number;
}

我们可以有这个功能:

const fetchUser1 = (userId: string): IUser => { 
  return {
    id: userId,
    name: 'John',
    age: 32,
  };
}

此函数无法返回不在 IUser 界面中的属性。

所以如果我们尝试返回一个新属性 city:

const fetchUser2 = (userId: string): IUser => { 
  return {
    id: userId,
    name: 'John',
    age: 32,
    city: 'Hollabrunn', // TS Error
  };
}

我们得到 TS 错误:Object literal may only specify known properties, and 'city' does not exist in type 'IUser' where 绝对是我们想要的。

现在让我们尝试为这个函数创建一个类型。

type TFetchUser = (userId: string) => IUser;

并实现这个Type的一个函数,同样会误返回city属性。

const fetchUser3: TFetchUser = (userId) => {
  return {
    id: userId,
    name: 'John',
    age: 32,
    city: 'Hollabrunn',
  };
};

现在问题来了,我们没有任何 TS 错误。city 属性是允许的!

尽管如果我们将name 属性输入错误为fullName,我们会得到TS 错误Property 'name' is missing in type...

谷歌搜索,我发现了一些关于接口这种奇怪行为的参考资料,但没有明确的解决方案。

你能帮忙吗?

Playground Link

【问题讨论】:

  • 您应该提供playground。我确认这是不正确的打字稿行为
  • 已添加游乐场链接
  • 你说的不一致很奇怪是绝对正确的,但我相信你把它倒过来了:第一个实例是错误的,第二个是正确的。具有所需属性的对象确实实现了IUser,即使它具有额外的属性。这样想,如果对象是一个类的实例,它使用“city”属性实现 IUser,它仍然是类型安全的。界面说“你必须至少做这么多才能符合”,而不是“你可以做这三件事”。

标签: typescript function interface


【解决方案1】:

规范 (3.11.5 Excess Properties) 提到检查多余的属性仅适用于使用新鲜对象文字的直接赋值。

在您的第一个示例中,对象文字直接尝试分配给 IUser 返回类型,这会引发检查(并正确地引发错误),但在第二个示例中,您有一个插入的步骤,起初可能并不明显.

由于未指定返回类型,因此推断该函数的返回类型为该对象字面量,而不是 IUser,这意味着返回语句完全有效,无需进一步检查。

然后将函数分配给需要返回类型为 IUser 的不同类型,这与您的对象的分配兼容,但到那时我们不再谈论分配对象字面量,可以放心地忽略检查多余的属性。

【讨论】:

    【解决方案2】:

    感谢 Jared Smith 和 Chris Hannon,解决方案是明确定义返回类型。

    否则,对于 TS,我们实现 IUser 并且在这种情况下允许使用新属性!

    const fetchUser3: TFetchUser = (userId): IUser => {
      return {
        id: userId,
        name: 'John',
        age: 32,
        city: 'Hollabrunn',  // Now we have the TS Error here
      };
    };
    

    【讨论】:

      猜你喜欢
      • 2021-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-12
      • 2021-11-13
      相关资源
      最近更新 更多