我想编写一个类型安全实用工具函数,用于比较Typescript 4.0中2个给定对象的属性。我最初的尝试如下:
export function propsAreEqual<O extends object, T extends O, S extends O>(first: T, second: S, props: (keyof O)[]) {
return props.every(prop => first[prop] === second[prop])
}
但是,使用此方法时出现编译错误TS2367,其中指出: This condition will always return 'false' since the types 'T[keyof O]' and 'S[keyof O]' have no overlap.
这个错误对我来说似乎违反直觉。如果两者T
和S
类型的扩展对象O
都没有,那么它们是否都必须都包含所有类型的键O
?如果有人能澄清我在这里想念的东西,以及对我要达到的目标有更合理的方法,我将不胜感激。
您得到的错误并非不正确,扩展O
只是意味着extends object
,而这又意味着您可以使用T = { a: number }
and O = { a: string }
(ex)。键是相同的,但T[keyof O]
和之间没有重叠O[keyof O]
。可能会有重叠,但是在处理TS时希望能够证明该函数对于type参数的任何有效实例都是正确的,并且正如我们在此处看到的,在某些情况下该函数无效。
您可能有几种方法来定义此函数,可以对第一个对象使用单个类型参数,然后将第二个对象定义为Pick
或传入的属性。
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 [K]类型相同。此版本的缺点是,如果尝试将对象文字作为第二个参数传递,则会启动多余的属性检查。另一个缺点是,intellisense将T
在第三个参数中建议所有属性,如果该属性不是常见的是,您会在第二个参数上看到错误。
就我个人而言,我更希望选择一个牺牲功能性的全类型检查作为回报,以解决上述两个问题。这将是此版本:
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])
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句