这是一个例子。假设我不控制数据格式。
type Thing = {
name: string
}
// if you canJump, you need to specify howHigh
type Jump = {
canJump: true
howHigh: number
}
// MightJump Things either jump or don't
type MightJump = Thing | (Thing & Jump)
const thing: MightJump = {
name: 'hi',
canJump: true,
// howHigh: 5, // how do I make commenting this out an error?
}
因此,理想情况下,对于类型为MightJump
的值,如果只设置了name
,则没关系,但如果设置了canJump
或howHigh
,则另一个那对也是必需的。
这在TypeScript中是否可行?如果没有,那么需要对编译器进行哪种改变才能支持它?我对限制的确切性质非常感兴趣。
据我所知,Thing | (Thing & Jump)
会产生一种类型,其中canJump
和howHigh
都是可选的,只需要name
。
更新:使用artem的答案:
type OptNever<T> = {
[K in keyof T]?: never
}
type AllOrNone<T> = T | OptNever<T>
type MightJump = Thing & AllOrNone<Jump>
答案 0 :(得分:1)
您需要确保联合的类型不兼容
type Thing = {
name: string
}
// if you canJump, you need to specify howHigh
type Jump = {
canJump: true
howHigh: number
}
// MightJump Things either jump or don't
type MightJump = (Thing & { canJump?: false } )| (Thing & Jump)
const thing: MightJump = {
name: 'hi',
canJump: true,
// howHigh: 5, // error
}
这对于检查额外的proepries如何为工会起作用有点古怪。通常,如果为对象文字指定了额外的属性,编译器会抱怨,但如果属性属于任何类型的并集,则不会。所以你的文字可以赋予Thing
一些额外的属性。如果我们明确地将其与Thing
不兼容,则会收到错误。
答案 1 :(得分:1)
您可以通过为其提供可选的never
类型来禁止在联合类型成员中存在属性:
type Thing = {
name: string
}
// if you canJump, you need to specify howHigh, and vice versa
type JumpOrNot = { canJump?: never; howHigh?: never} | {
canJump: true
howHigh: number
}
// MightJump Things either jump or don't
type MightJump = Thing & JumpOrNot
const thing: MightJump = {
name: 'hi',
canJump: true,
// error
// Type '{ name: string; canJump: true; }' is not assignable to type 'MightJump'.
// Type '{ name: string; canJump: true; }' is not assignable to type 'Thing & { canJump: true; howHigh: number; }'.
// Type '{ name: string; canJump: true; }' is not assignable to type '{ canJump: true; howHigh: number; }'.
// Property 'howHigh' is missing in type '{ name: string; canJump: true; }'.
}
const thing1: MightJump = {
name: 'thing1'
}
const thing2: MightJump = {
name: 'thing2',
canJump: true,
howHigh: 5,
}
答案 2 :(得分:1)
一种方法是使用否定类型,例如:
type CantJump = {
canJump?: undefined
howHigh?: undefined
}
然后您的MightJump
类型将
type MightJump = Thing & ( Jump | CantJump )
这样就可以强制执行这两个属性,也可以不执行任何属性。
unlike
关键字目前有一个proposal,可能允许这样的内容:
type MightJump = Thing & ( Jump | unlike Jump )
然而,正在等待更多反馈,这意味着没有足够的支持。