首页 > 解决方案 > 使用标签泛型创建接口外的联合

问题描述

我目前有一个 typeorm 类,我希望有特定的功能,我可以用这个Or泛型“标记”属性。下面在我的示例中,我使用的是接口,但想法应该是相同的。

我想做这样的事情:

export type Or<T, B> = T & { or?: undefined };

interface Example { 
  name: Or<string, 'firstName' | 'lastName'>
  firstName: Or<string, 'name'>
  lastName: Or<string, 'name'>
}

我想传递Example给另一个泛型Build<Example>,让它变成这样:

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 E = StrictUnion<
  { firstName: string, lastName: string } |
  { name: string }
>

这样的事情可能吗?

更新:

这是一个正确的方向:

type Build<T> = StrictUnion<{ [P in keyof T]: T[P] extends { or: any } ? Pick<T, T[P]['or']> : never }[keyof T]>

const v:Build<Example> = { 
  name: 'hi'
}

标签: typescript

解决方案


export type Or<T, B> = T & { or?: B };

interface Example { 
  name: Or<string, 'firstName' | 'lastName'>
  firstName: Or<string, 'name'>
  lastName: Or<string, 'name'>
}

type Build<T> = StrictUnion<{ [P in keyof T]: T[P] extends { or?: any } ? Pick<T, T[P]['or']> : never }[keyof T]>

type Working = Build<Example>

const a: Working = { 
  firstName: 'meow',
  lastName: 'woof'
}

const b: Working = { 
  name: 'meow'
}

推荐阅读