【发布时间】:2019-11-14 15:20:10
【问题描述】:
在构建某些库的类型安全版本时,我遇到了涉及复杂映射类型的问题并卡住了。
这是此问题的简化版本。我们有两种“盒装”类型——Strong<T> 和Weak<T>,对应的可以认为是“持有一个值”和“可能持有一个值”。然后,有一个包含这些“盒子”的对象,我需要编写一个函数,通过将 Strong<T> 转换为 T 和 @ 987654329@ 到 T 类型的可选字段。稍后,在代码的其他部分,我会将类型Strong<T>“拆箱”为T。
问题是我无法使这些字段有条件地成为可选字段。有问题的代码如下所示:
type Strong<T> = { __phantom?: T, marker: 'strong' };
type Weak<T> = { __phantom?: T, marker: 'weak' };
// helper functions, to be used later
function strong<T>(): Strong<T> {
return { marker: 'strong' };
}
function weak<T>(): Weak<T> {
return { marker: 'weak' };
}
// input type for my function
type Rec = { [index: string]: Strong<unknown> | Weak<unknown> };
// output type for my function; how to define it?
type Unified<T extends Rec> = { __phantom?: T, marker: 'unified' };
// put there something, just so that this type is unique
function unify<T extends Rec>(input: T): Strong<Unified<T>> {
// implementation is irrelevant now
return {} as any;
}
// when we have the Strong value, we can 'unbox' the type
type Unboxed<T> = T extends Strong<infer I> ? I : never;
// ...so, how to make this compile?
const unified = unify({ strong: strong<string>(), weak: weak<string>() });
const valid: Array<Unboxed<typeof unified>> = [{ strong: '' }, { strong: '', weak: '' }];
// ...and at the same time forbid this?
const invalid: Array<Unboxed<typeof unified>> = [{}, {weak: ''}, {unknown: ''}]
一种尝试是合并所有对象值,对其进行转换,然后使用UnionToIntersection 进行转换,但该类型足够复杂,以至于类型推断会卡住并吐出一堆unknowns。
如何定义Unified 类型以正确派生自输入?
【问题讨论】:
标签: typescript