gpt4 book ai didi

typescript - 如何定义对象类型的真正逻辑 OR(结果中不混合不同的对象键)

转载 作者:行者123 更新时间:2023-12-04 15:04:39 24 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Why does A | B allow a combination of both, and how can I prevent it?

(3 个回答)



Type union not checking for excess properties

(2 个回答)


9 个月前关闭。




一个例子:

type TA = {a:number,b:number}
type TB = {a:number,c:number,d:number}
const t1:Or<TA,TB> = {a:1,b:1} // want
const t2:Or<TA,TB> = {a:1,c:1,d:1} // want
const t3:Or<TA,TB> = {a:1,b:1,c:1} // DON'T want
期望的结果是 t1有效,因为它完全适合 TA , 和 t2有效,因为它完全适合 TB , 但对于 t3无效,因为它不完全适合 TATB .
什么时候
type Or<T,U>=T|U
TypeScript 实际上考虑了 t3有效。 TypeScript 联合类型 |还允许合并键对象,有时还允许合并部分对象。
将每种类型放在单个元素数组中,如下所示:
type T0 = {a:number,b:number}
type T1 = {a:number,c:number,d:number}
type Test=[T0]|[T1]
const t1:Test=[{a:1,b:1,}]
const t2:Test=[{a:1,c:1,d:1}]
const t3:Test=[{a:1,b:1,c:1}] // fails as desired
工作,但被测对象也必须放在单元素数组中。
有什么办法可以解决这个问题吗?

最佳答案

为什么
在 typescript 中,|不是运算符*,它表示该类型是左侧和右侧类型的联合。如果您要了解原因 {a:number,b:number} | {a:number,c:number,d:number},了解这一点很重要。允许 {a:number,b:number,c:number} .
当你声明一个联合时,你告诉编译器一个可分配给联合的类型应该至少可以分配给它的一个成员。考虑到这一点,让我们检查 {a:number,b:number,c:number}从这个角度打字。
工会的左侧成员是 {a:number,b:number} ,这意味着可分配给它的类型必须至少有 2 个类型为 number 的属性。 :ab (对于对象文字有 excess property checks 的概念,但是,正如 T.J. Crowder 的 mentioned 一样,这不适用于联合)。来自 the handbook **:

the compiler only checks that at least the ones required are present and match the types required


因此,由于 {a:number,b:number,c:number}可分配给 {a:number,b:number}不再需要检查 - 类型至少满足联合的一项要求。顺便说一句,这种行为完全符合逻辑 OR 的真值表,这类似于联合。

您通过将类型包装成元组来解决此问题的尝试依赖于 naked vs. wrapped类型参数行为。因为您将类型包装在元组中,所以编译器会将一个元素的元组相互比较。显然,第三个元组与第一个和第二个元组不同,这会为您提供所需的结果。

什么
您真正想要的是逻辑异或所表现出的行为:其中之一,但不是两者。除了使用 tagged types ( mentioned by T.J. Crowder),可以定义一个实用程序,将一对类型转换为“来自 A 的所有 Prop 都存在于两者中,但不单独存在于 A”类型的联合:
type XOR<A,B> = ({ [ P in keyof A ] ?: P extends keyof B ? A[P] : never } & B) | ({ [ P in keyof B ] ?: P extends keyof A ? B[P] : never } & A);
这是它的工作原理(该实用程序的权衡是将多余的属性泄露给智能感知,但由于 never 立即不允许指定它):
const t0:XOR<TA,TB> = {a:1} //property 'b' is missing
const t1:XOR<TA,TB> = {a:1,b:1} // OK
const t2:XOR<TA,TB> = {a:1,c:1,d:1} // OK
const t3:XOR<TA,TB> = {a:1,b:1,c:1} // types of property 'c' are incompatible
Playground

* |的概念运算符(operator)出现在 first revision 中后来被删掉了
** 必须注意,这并不意味着找到匹配项时所有检查都短路。在这种情况下,联合的所有成员本身都是对象字面量,因此对已知属性的约束仍然适用于每个成员,如果在赋值期间存在未知属性,则会导致 TS2322 错误:
const t4:XOR<TA,TB> = {a:1,b:1,c:1, g:3} //Object literal may only specify known properties

关于typescript - 如何定义对象类型的真正逻辑 OR(结果中不混合不同的对象键),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66382997/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com