微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

TypeScript 如何使字符串联合类型成为具体的对象类型?

如何解决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. union 在 ts extends 子句中的协方差。

解决方法

这是一个简单的mapped type

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

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

在这里,我们将 constraining U 设为类似于键,而不是通过条件类型进行检查。如果你真的想这样做,你可以用这样的解决方案:

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

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

Playground link to code

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。