为什么Typescript Array.map的返回类型允许违反接口?

时间:2019-11-26 10:56:10

标签: typescript

我期望下面的Typescript代码失败,并向is not assignable接口添加here时出现ImyWrapper错误。但是,没有错误发生,我想解释一下。

interface ImyItem {
    id: string;
}

interface ImyWrapper {
    item: ImyItem;
}

class Test {
    private itemWrappers: ImyWrapper[] = [];

    bar() {
        const item1: ImyItem = { id: "one" };
        const item2: ImyItem = { id: "two" };
        const items = [item1, item2];

        this.itemWrappers = items.map(item => {
            return { item, here: "why does this not cause error?" };
        });
    }
}

这是Typescript Playground

中的代码

1 个答案:

答案 0 :(得分:2)

关于TypeScript中类型兼容性的几件重要事情

  

TypeScript中的类型兼容性基于结构子类型。

  

TypeScript结构类型系统的基本规则是,如果y与x至少具有相同的成员,则x与y兼容

这意味着如果Y具有X类型的所有必需属性,则可以将Y类型分配给X类型。换句话说,如果Y是X的超集,则可以将其分配给X。

我们可以说-如果Y在结构上扩展了X,则Y可分配给X

此问题确实存在。

a = { item, here: "why does this not cause error?" }
// a has structure which has a type:
interface ImplicitAType {
   item: ImyItem
   here: string
}

// the wanted structure is
interface ImyWrapper {
    item: ImyItem;
}
// below we can have a prove of that, this evaluates to true
type DoesAExtendsWrapper = ImplicitAType  extends ImyWrapper  ? true : false; 

因此,我们证明了返回的类型扩展了您分配的类型,这意味着-由于结构子类型语言的行为,类型系统完全允许它返回。您可以在这里阅读更多内容-Type Compatibility

您可以通过严格定义映射函数的输出来严格执行以下操作:

this.itemWrappers = items.map((item): ImyWrapper => {
            return { item, here: "now it is an error!" };
        });