Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript中的相交键_Typescript_Typescript Generics - Fatal编程技术网

Typescript中的相交键

Typescript中的相交键,typescript,typescript-generics,Typescript,Typescript Generics,我想编写一个类型安全实用程序函数,用于比较Typescript 4.0中两个给定对象的属性。我的初步尝试如下: 导出函数propsAreEqual(第一个:T,第二个:S,props:(keyof O)[])){ 返回道具。每隔(道具=>第一个[道具]==第二个[道具]) } 但是,使用这种方法,我得到一个编译错误TS2367,它指出: 此条件将始终返回“false”,因为类型“T[keyof O]”和“S[keyof O]”没有重叠。 这个错误对我来说似乎是违反直觉的。如果T和S都扩展了O类

我想编写一个类型安全实用程序函数,用于比较Typescript 4.0中两个给定对象的属性。我的初步尝试如下:

导出函数propsAreEqual(第一个:T,第二个:S,props:(keyof O)[])){
返回道具。每隔(道具=>第一个[道具]==第二个[道具])
}
但是,使用这种方法,我得到一个编译错误TS2367,它指出:
此条件将始终返回“false”,因为类型“T[keyof O]”和“S[keyof O]”没有重叠。


这个错误对我来说似乎是违反直觉的。如果
T
S
都扩展了
O
类型的对象,那么它们不都必须包含
O
类型的所有键吗?如果有人能澄清我在这里遗漏了什么,以及我试图实现的目标是否有更合理的方法,我将不胜感激。

当您推断一个类型参数时,Typescript只想从其中一个参数推断它;因此签名
propsAreEqual(a:T,b:T,props:(keyof T)[])
不起作用,因为Typescript从第一个参数的类型推断
T
,然后在发现第二个参数不可分配给该类型时,不会尝试松开它

解决方案:使用将从
props
推断的泛型类型,而不是从
a
b
推断的泛型类型

function propsAreEqual<K extends PropertyKey>(a: Record<K, unknown>, b: Record<K, unknown>, props: K[]) {
    return props.every(prop => a[prop] === b[prop]);
}
function-propsAreEqual(a:Record,b:Record,props:K[]){
返回props.every(prop=>a[prop]==b[prop]);
}

您得到的错误不是不正确的,扩展
O
只意味着扩展
对象
,而这又意味着您可以拥有
T={a:number}
O={a:string}
()。键是相同的,但是
T[keyof O]
O[keyof O]
之间没有重叠。可能存在重叠,但在处理TS时,我们希望能够证明该函数对于类型参数的任何有效实例化都是正确的,正如我们在这里看到的,在某些情况下,该函数是无效的

您可以使用多种方法来定义此函数。您可以对第一个对象使用单个类型参数,并将第二个对象定义为
拾取
或传入的属性

function propsAreEqual<T extends object, K extends keyof T>(first: T, second: Pick<T, K>, props: K[]) {
    return props.every(prop => first[prop] === second[prop])
}

这也是一个非常有趣的解决方案,但在功能上似乎与@t-j-crowder提供的示例相当,尽管编写得更简洁。我的问题是,TS是否可以从提供的对象推断
props
参数的类型,因为这在原则上是可能的。这与T.J.Crowder回答中的任何一个示例都不等价。请注意,他的第一个示例不符合要求,第二个示例有三个类型参数和一个类型断言。我的意思是,从根本上说,它们都使用给定的数组进行类型推断,然后验证提供的对象,不是吗?我只是想知道是否有可能用另一种方法,也就是让TS推断出两种类型的公共属性,然后用它来验证给定的数组。这在功能上是不同的,因为它还可以启用代码完成。我明白你关于代码完成的意思,但我认为问题是Typescript仅从一个参数推断类型参数,而不是两个参数的公共属性,如果两个参数有两个不同的类型参数(允许它们不同),然后,您将得到关于条件始终为false的错误(逻辑上不正确)。我不能确定是否存在解决方法,但直觉上我似乎不太可能。我很高兴看到我基本正确地找到了错误的原因。:-)很好的解决方案!我想我没有意识到类型参数可以有这样的循环引用。哇,太酷了。的确,@t-j-crowder,你猜对了。遗憾的是,你的答案被删除了。:/@titian cernicova dragomir的最终解决方案似乎正是我想要的,即从对象类型推断数组类型。“扩展
O
仅仅意味着扩展
对象”
“哦,好吧,这就更清楚了。关于TS是如何推断类型的,我又一次有了错误的假设…@arslancharyev31-非常好。:-)但我认为我的回答没有给提香带来任何价值。我可以取消删除它,如果你愿意,但上面涵盖的要点很好。快乐编码!
function propsAreEqual<T extends object,  S extends Pick<T, K>,  K extends keyof T & keyof S>(first: T, second: S, props: K[]) {
    return props.every(prop => first[prop] === (second as Pick<T, K>)[prop])
}