类型映射返回联合的类型映射成员的交集

时间:2018-10-29 02:37:23

标签: typescript generics

我的类型安全查询构建器中具有以下数据类型。

// types
type SUDI = S | U | D | I
type SUD = S | U | D
type S = 'Select'
type U = 'Update'
type D = 'Delete'
type I = 'Insert'

// states
interface STATE_SUDI { state: 'SUDI' }
interface STATE_SUD { state: 'SUD' }
interface STATE_S { state: 'S' }
interface STATE_U { state: 'U' }
interface STATE_D { state: 'D' }
interface STATE_I { state: 'I' }

您可以在类型和状态之间进行转换。

type TypeToState<T> = 
  SUDI extends T ? STATE_SUDI :
  SUD extends T ? STATE_SUD :
  S extends T ? STATE_S :
  U extends T ? STATE_U :
  D extends T ? STATE_D :
  I extends T ? STATE_I : never;

type StateToType<T> = 
  T extends STATE_SUDI ? SUDI :
  T extends STATE_SUD ? SUD :
  T extends STATE_S ? S :
  T extends STATE_U ? U :
  T extends STATE_D ? D :
  T extends STATE_I ? I : never;

状态数组的类型是所有状态类型的并集的数组。例如:

declare let array: (STATE_SUDI | STATE_SUD)[]

当数组元素的类型与StateToType映射时,它变为:

StateToType<STATE_SUDI | STATE_SUD>
// = StateToType<STATE_SUDI> | StateToType<STATE_SUD>
// = SUDI | SUD
// = (S | U | D | I) | (S | U | D)
// = (S | U | D | I)
// = SUDI

我想要的行为是在联合的每个成员上应用StateToType,然后得到交点。

BetterStateToType<test>
// = StateToType<STATE_SUDI> & StateToType<STATE_SUD>
// = SUDI & SUD
// = (S | U | D | I) & (S | U | D)
// = (S | U | D)
// = SUD

我需要定义BetterStateToType的帮助。

我知道可以将并集转换为相交,但是我无法弄清楚是否还可以在相交之前应用映射。

Transform union type to intersection type

Intersection of mapped types

1 个答案:

答案 0 :(得分:1)

是的,这是可能的:

type BetterStateToType<T> =
  (T extends any ? ((x: [StateToType<T>]) => void) : never) extends
  ((x: [infer I]) => void) ? I : never

type StateToTypeSuSussudio = BetterStateToType<STATE_SUDI | STATE_SUD>;
// = SUDI & SUD
// = (S | U | D | I) & (S | U | D)
// = (S | U | D)
// = SUD
// = "Select" | "Update" | "Delete"

它类似于常规的联合路口代码:

type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

但是它使用U代替[StatetoType<T>],而[SUDI] | [SUD]变成了SUDI | SUD之类的东西。单元素元组“框”阻止编译器评估SUDI,而[SUDI] | [SUD]立即折叠为never,而type NotSure = BetterStateToType<STATE_S | STATE_U> // = "Select" & "Update", not gonna happen 则保持不变,直到并集相交发生为止。

我猜您对这样的StateToType<>类似结果感到满意:

type StateTypeMap = {
  SUDI: SUDI
  SUD: SUD
  S: S
  U: U
  D: D
  I: I
}
type StateToType<T extends { state: keyof StateTypeMap }> =
  StateTypeMap[T['state']];

顺便说一句,如果我不必使用条件类型,我倾向于避免使用条件类型,因此我更倾向于像这样定义 public override void Initialize(AnalysisContext context) { context.RegisterCompilationAction(AnalyzeCompilation); } private void AnalyzeCompilation(CompilationAnalysisContext context) { var compilation = context.Compilation; int referenceCount = compilation.References.Count(); if (referenceCount > 1) { context.ReportDiagnostic(Diagnostic.Create(Rule, null, compilation.AssemblyName, referenceCount)); } }

SELECT SDO_UTIL.TO_WKBGEOMETRY (GEOMETRY),
       S_ROUTE,
       BLOCK_ID
  FROM GEOM_TABLE;

我想这大致相同。


希望有所帮助;祝你好运!