如何使字符串联合类型到一个具体的对象类型?



如何实现这个:

type ActionNames = 'init' | 'reset';
type UnionToObj<U> = {/* TODO HERE */}
type Result = UnionToObj<ActionNames>;
// expect type Result to be `{ init: any, reset: any }`

我已经写了一个实现,但是它不能正常工作,它遇到联合扩展协方差问题:

type UnionToObj<U> = U extends string ? { [K in U]: any } : never;
type Result = UnionToObj<'init' | 'reset'>;
// expecting the type Result to be `{ init: any, reset: any }`
// but i got a union object: `{ init: any } | { reset: any }`
// how do i resolve it ?

主要问题:

  1. 字符串联合类型到对象类型
  2. union的协方差在extends子句中

这是一个简单的映射类型:

type UnionToObj<U extends PropertyKey> = { [K in U]: any }
type Result = UnionToObj<ActionNames>;
/* type Result = {
init: any;
reset: any;
} */

这里我们将U约束为类键,而不是通过条件类型检查它。如果你真的想这样做,你可以用这样的解决方案:

type UnionToObj<U> = [U] extends [PropertyKey] ? { [K in U]: any } : never;

这个和你的版本的区别在于你的版本无意中是一个分布条件类型。由于您不希望联合输入变成联合输出,因此您需要防止条件类型分布,方法是不让U extends ...直接在已检查的位置带有裸类型参数。将被检查的类型包装在一元组([U] extends ...)中足以关闭联合分布。

Playground链接到代码

最新更新