打字稿:为什么这种通用合并会失败?

时间:2017-10-30 14:20:25

标签: typescript types

在Typescript 2.5.3中给出这些类型......

type Data<T> = {
    [K in keyof T]?: T[K]
}

interface Merge {
    body: {
        isMerged: boolean
    }
}

interface Args {
    one: number
    two: number
}

为什么这个函数无法编译:

function merge<T>(data: Data<T>): Merge & { body: Data<T> } {
    const merged = {
        body: {
            isMerged: true
        }
    }

    // Written this way to guarantee { body: isMerged } remains intact
    merged.body = Object.assign({}, data, merged.body);

    return merged;
}

enter image description here

然而这个电话......

const m = merge<Args>({
    one: 1,
    two: 2,
});

...正确推断返回的数据?

enter image description here

修改

我意识到显式地将返回类型转换为:

return <Merge & { body: Data<T> }> merged;

...抑制错误,但我的问题是为什么不能在以下情况下推断出类型:

  • 它知道函数签名中的返回类型
  • 可以看到未对身体中的data进行任何更改

编辑2和结论/回答:

根据Titian Cernicova-Dragomir的回答,TL; DR似乎是这样的:最初定义的类型是指定的类型。 类型不会变形。

我希望Typescript知道向类型添加额外的键会使它最终满足返回类型接口,但似乎最初定义的类型是坚持的类型。

因此,该功能应为:

function merge<T>(data: Data<T>): Merge & { body: Data<T> } {
    const merged ={
        body : Object.assign({}, data, {
            isMerged: true
        })
    };
    return merged;
}

即。在一个表达式中定义merged,而不是添加到多个表达式中。

1 个答案:

答案 0 :(得分:2)

问题在于,当您尝试将const merged分配给身体为{ isMerged: boolean } & Data<T>的内容时,您的Data<T>将使用您设置的主体(仅具有isMerged属性的对象)进行输入它会失败,因为没有办法告诉该对象将满足function merge<T>(data: Data<T>): Merge & { body: Data<T> } { const merged ={ body : Object.assign({}, data, { isMerged: true }) }; return merged; } 接口。尝试:

00000  Andy   8920  N  UNL  ...
00001  Roger  4428  N  TRX  ...
,,,