首页 > 解决方案 > TypeScript 如何将字符串联合类型转换为具体的对象类型?

问题描述

我该如何实现:

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. ts extends 子句中的联合协方差。

标签: typescriptgenericscovarianceunion-types

解决方案


这是一个简单的映射类型

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

type Result = UnionToObj<ActionNames>;
/* type Result = {
    init: any;
    reset: any;
} */

在这里,我们限制 U为 key-like,而不是通过条件类型检查它。如果你真的想这样做,你可以使用这样的解决方案:

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

这个和你的版本的区别在于你的版本无意中是一个分布式条件类型。由于您不希望联合输入成为联合输出,因此您需要通过U extends ...在选中位置不直接使用裸类型参数来防止条件类型分布。将选中的类型包装在一个单元组 ( [U] extends ...) 中足以关闭联合分布。

Playground 代码链接


推荐阅读