首页 > 解决方案 > 对返回对象字面量的 Array.map 进行类型检查

问题描述

我在 TypeScript 游乐场创建了这个示例:

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 对接口上缺少的属性进行类型检查,而不是对附加/未知属性进行类型检查?

标签: typescript

解决方案


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

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

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

推荐阅读