【问题标题】:Type checking on Array.map that returns object literals对返回对象字面量的 Array.map 进行类型检查
【发布时间】:2019-05-14 10:15:33
【问题描述】:

我在 TypeScript 游乐场创建了 this example

interface Test{
    a: string
    b: string
}

const object: Test = {
    a: 'b',
    b: 'c',
}

function testIt(): Test[] {
    const data = [{b: '2', c: '3'}]
    const prices: Test[] = data.length ? data.map((item) => {
        return {
            a: item.b,
            b: item.c,
            c: '2',
            d: '3'
        }
    }) : [];
    return prices;
}

从数组映射方法中的对象返回语句中删除 a 或 b 属性会导致 TypeScript 错误(如预期的那样)。

添加 c 或 d 或任何其他随机未知属性不会触发 TypeScript 错误。我怀疑这只有在接口包含 [x: string]: any 时才有可能。

那么为什么 Array.map 对接口上缺失的属性进行类型检查,而不是对附加/未知属性进行类型检查?

【问题讨论】:

  • 因为要匹配接口,您必须实现它声明的所有内容。但是您可以拥有其他方法/属性,它仍然与所需的实现相匹配。
  • 错了。如果您将c: 'test' 添加到上面示例中的 const 对象,您仍然会收到错误消息。对于动态属性,需要添加[x:string]:any;。但在这种情况下,不在 Array.map 中,这让我觉得很奇怪。
  • 这是因为在这种情况下您使用的是对象文字,打字稿不允许来自基类型的未知属性。在 map 函数中,你让 typescript 推断出它工作的原因。

标签: typescript


【解决方案1】:

问题在于,根据基本 OOP 规则,派生类型(即具有更多属性的类型)应与基类型(即仅具有 ab 的类型)兼容。

话虽如此,打字稿确实会在为具有更多属性的对象字面量分配预期具有更少属性的类型时警告我们。这称为多余的属性检查。此功能仅在直接分配给给定类型的内容时才起作用。

这种多余的属性检查不适用于您的情况的原因是对map 进行类型检查的方式。首先根据对象字面量推断回调返回类型,因此推断为{ a: string, b: string, c: string, d: string }。然后这个类型被用作map的返回类型,所以map会返回一个Array<{ a: string, b: string, c: string, d: string }>。然后将其分配给Test[],根据第一条规则是允许的。我们没有在任何地方将对象字面量分配给需要 Test 的地方。

获得错误的一种方法是不让 typescript 推断传递给map 的回调结果。我们可以通过在回调中添加注解来做到这一点。然后我们直接将一个对象字面量分配给一个需要Test的位置:

const prices = data.length ? data.map((item) : Test => {
    return {
        a: item.b,
        b: item.c,
        c: '2', // error
        d: '3'
    }
}) : [];

【讨论】:

  • 我希望data.map 隐式返回Array<{ a: string, b: string, c: string, d: string }>,这与Test[] 不匹配。仍然 data.map 足够聪明,可以找出缺失的属性。为什么不进行完整的精确类型检查?我的意思是,在什么用例中你会想要这种行为?
  • @KeesvanLierop 为什么不马赫?允许分配,你能在Test[] 上做任何在Array<{ a: string, b: string, c: string, d: string }> 上无效的事情吗? { a: string, b: string, c: string, d: string } 派生自 TS 使用的结构类型系统下的 Test,因此您将派生对象的数组分配给基础对象的数组。
  • @KeesvanLierop 您可以在文档中阅读更多内容:typescriptlang.org/docs/handbook/interfaces.html under extra property
  • 请接受正确答案并感谢@TitianCernicova-Dragomir!
猜你喜欢
  • 2020-06-13
  • 1970-01-01
  • 2011-07-09
  • 2020-11-25
  • 2017-10-12
  • 2019-07-05
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
相关资源
最近更新 更多