Typescript 允许额外属性的StrictUnion
鉴于此Typescript 允许额外属性的StrictUnion,typescript,typescript-generics,Typescript,Typescript Generics,鉴于此StrictUniongeneric: type UnionKeys<T> = T extends T? keyof T : never; type StrictUnionHelper<T, TAll> = T extends T? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, undefined>> : never; export type Str
StrictUnion
generic:
type UnionKeys<T> = T extends T? keyof T : never;
type StrictUnionHelper<T, TAll> = T extends T? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, undefined>> : never;
export type StrictUnion<T> = StrictUnionHelper<T, T>
type Working = StrictUnion<(
{ id: number } |
{ uuid: string } |
{ memberId: number } |
{ memberUuid: string } |
{ member: Member } |
{ organizationId: number, contactId: number })
>
const a: Working = { id: 1 }
const b: Working = { uuid: '123456' }
const c: Working = { organizationId: 1, contactId: 1 }
const d: Working = { organizationId: 1 }
const e: Working = { id: 1, organizationId: 1, contactId: 1 } // I would like this to work
const f: Working = { }
我正在寻找匹配项,以匹配至少一个联合,但也允许额外的属性,这意味着您不能只传递organizationId
,因为它需要contactId
,但您可以只传递id
,而不能传递empty
{}
如果你使用普通工会的问题是,如果有办法使用普通工会解决这些问题,我会接受这一解决方案
更多想法:
type Requirements = (
{ id: number } |
{ uuid: string } |
{ memberId: number } |
{ memberUuid: string } |
{ member: Member } |
{ organizationId: number, contactId: number }
)
✅ Should be valid
❌ Should not be valid
const a: Requirements = { id: 1 } ✅
const b: Requirements = { uuid: '123456' } ✅
const c: Requirements = { id: null, uuid: null } ✅ (will throw, but valid)
const d: Requirements = { uuid: '123456', contactId: 1 } ✅
const e: Requirements = { organizationId: 1, contactId: 1 } ✅
const f: Requirements = { uuid: '12345', organizationId: 1, contactId: 1 } ✅
const g: Requirements = { uuid: null, organizationId: 1, contactId: 1 } ✅
const h: Requirements = { organizationId: 1 } ❌
const i: Requirements = { id: 1, organizationId: undefined } ✅
const j: Requirements = { } ❌
我喜欢AtLeastOne
的功能:
type AtLeastOne<T, U = {[K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U]
你能用普通的工会吗?它本身也不应该允许“{organizationId:1}”。@ProdigySim添加了关于常规联合不起作用的原因的上下文。@ThomasReggi如果
id
在联合的一个组成部分中有效,为什么不直接添加它,即使它是可选的({organizationId:number,contactId:number,id?:number}
)。如果您希望允许来自任何成员的成员加入,为什么不使用常规联盟?从上面的代码中,我不清楚你是否可以将id
从一个连续剧混搭到另一个连续剧中,为什么StrictUnion
是必要的。@TitianCernicova Dragomir是的,我同意我开始理解我想要的东西的复杂性。1) 我不希望empty起作用,2)我希望需要特定的对(即使它们为null或未定义)。我有类型AtLeastOne=Partial&U[keyof U]
,但这不适合成对使用。3) 我确实希望额外的undefined
或null
也能正常工作。有什么想法吗?比如说?你能用一个固定的联盟吗?它本身也不应该允许“{organizationId:1}”。@ProdigySim添加了关于常规联合不起作用的原因的上下文。@ThomasReggi如果id
在联合的一个组成部分中有效,为什么不直接添加它,即使它是可选的({organizationId:number,contactId:number,id?:number}
)。如果您希望允许来自任何成员的成员加入,为什么不使用常规联盟?从上面的代码中,我不清楚你是否可以将id
从一个连续剧混搭到另一个连续剧中,为什么StrictUnion
是必要的。@TitianCernicova Dragomir是的,我同意我开始理解我想要的东西的复杂性。1) 我不希望empty起作用,2)我希望需要特定的对(即使它们为null或未定义)。我有类型AtLeastOne=Partial&U[keyof U]
,但这不适合成对使用。3) 我确实希望额外的undefined
或null
也能正常工作。有什么想法吗?比如?
type Requirements = (
{ id: number } |
{ uuid: string } |
{ memberId: number } |
{ memberUuid: string } |
{ member: Member } |
{ organizationId: number, contactId: number }
)
✅ Should be valid
❌ Should not be valid
const a: Requirements = { id: 1 } ✅
const b: Requirements = { uuid: '123456' } ✅
const c: Requirements = { id: null, uuid: null } ✅ (will throw, but valid)
const d: Requirements = { uuid: '123456', contactId: 1 } ✅
const e: Requirements = { organizationId: 1, contactId: 1 } ✅
const f: Requirements = { uuid: '12345', organizationId: 1, contactId: 1 } ✅
const g: Requirements = { uuid: null, organizationId: 1, contactId: 1 } ✅
const h: Requirements = { organizationId: 1 } ❌
const i: Requirements = { id: 1, organizationId: undefined } ✅
const j: Requirements = { } ❌
type AtLeastOne<T, U = {[K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U]
AtLeastOne<{
id: number,
uuid: string,
memberId: number,
memberUuid: string,
member: Member,
organizationId: number,
contactId: number
}>
PartialPairs<
{ id: number } |
{ uuid: string } |
{ memberId: number } |
{ memberUuid: string } |
{ member: Member } |
{ organizationId: number, contactId: number }
>
AtLeastOne<{
{ id: number } |
{ uuid: string } |
{ memberId: number } |
{ memberUuid: string } |
{ member: Member } |
{ organizationId: number, contactId: number }
}>