【发布时间】:2021-06-23 15:15:10
【问题描述】:
我创建了一个通用实用函数,它接受 2 个Objects 并将它们合并在一起。作为第二个参数传递的 Object 也将覆盖与作为第一个参数传递的 Object 重叠的键。
/**
* Deeply merges two objects together with the source object overwriting the matching keys in the destination object.
*
* @param destination The object into where the source will be merged.
* @param source The object to merge into destination. (overwrites keys in destination).
* @returns A deep copy of the merged source and destination objects.
*/
export function deepMerge<T extends Object, K extends Object>(
destination: T,
source: K
): T & K {
const OUTPUT = deepCopy(destination) as T & K; //deepCopy<T extends Object>(obj: T): T Deep copies the object and returns it.
const keys = Object.getOwnPropertyNames(source) as Array<keyof K>;
for (const name of keys) {
const value = source[name];
if (
getCorrectType(value) === "object" &&
getCorrectType(OUTPUT[name]) === "object"
) {
OUTPUT[name] = deepMerge(OUTPUT[name], value);
} else {
OUTPUT[name] = value as (T & K)[keyof K];
}
}
return OUTPUT;
}
type Dest = {
readonly key: "I am a Key"
}
type Source = {
readonly key: "I should overwrite Dest key"
}
const dest1 = {
key: "Just a key"
}
const source1 = {
key2: "another key"
}
const dest2 = {
key: "Just another key"
}
const source2 ={
key: "Same key as dest1 so I will overwrite"
}
const dest3: Dest = {
key:"I am a Key"
}
const source3: Source = {
key: "I should overwrite Dest key"
}
const dest4 = {
key: 'I am a string'
}
const source4 = {
key: 90 //type number should overwrite dest4 type string
}
//Expect merged object of dest1 and source1
const res1 = deepMerge(dest1,source1)
//res1 = {key: string, key2: string} -> PASS
//Expect merged object of dest2 and source2 with only one key as the source2 key will overwrite dest2 key
const res2 = deepMerge(dest2, source2);
//res2 = {key: string} -> PASS
//Expect merged object of dest3 and source3 with source3 string literal overwriting dest3 string literal
const res3 = deepMerge(dest3, source3)
//res3 = never -> FAIL
//Expect merged object of dest4 and source4 with key of type number overwriting key of type string
const res4 = deepMerge(dest4, source4)
//res4 = {key: never} -> FAIL
当我使用不同的键传入Objects 时,Typescript 似乎正确评估了返回类型,但是,使用具有重叠键的对象;我开始得到never 或{key: never} 的返回类型
据我了解,never 暗示“类型”永远不会出现,尽管我不明白 typescript 是从哪里得出这个结论的。该函数在 vanilla JS 中按预期工作,所以我在声明类型时显然犯了一些错误。
有人可以帮助我了解 never 的来源,以及如何避免它吗?谢谢!
【问题讨论】:
-
如果你说
T & K,而T就是例如{ p: string },而K是{ p: number },那么属性需要同时是字符串和数字,这根本不可能。type X = string & number;、X将是never。 -
请将代码的相关部分也编辑到问题中,这样它就不仅仅是编码在 URL 中。命名约定注意:泛型类型参数
K一般用于指代键类型。如果您有类型T和K和K不扩展keyof任何东西,那就令人困惑了。我建议将K更改为U之类的东西,对于T的伴侣类型,这更像是conventional。 -
@jcalz 谢谢你,我会编辑代码并将 K 替换为 U 并在我的评论中添加代码的相关部分
-
@ASDFGerte 这是有道理的,感谢您澄清!
标签: javascript typescript typescript-generics