对返回对象文字的 Array.map 进行类型检查

Kee*_*rop 7 typescript

我在 TypeScript playground创建了这个例子

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Tit*_*mir 7

问题是,根据基本的 OOP 规则,派生类型(即具有更多属性的类型)应该与基类型(即只有a和的类型)兼容b

话虽如此,打字稿确实会在分配具有更多属性的对象文字时警告我们,而期望具有较少属性的类型。这称为过度属性检查。此功能仅在对给定类型的内容进行 DIRECT 分配时起作用。

这种多余的属性检查不适用于您的情况的原因是对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'
    }
}) : [];
Run Code Online (Sandbox Code Playgroud)

  • 请接受正确答案并感谢@TitianCernicova-Dragomir! (2认同)