gpt4 book ai didi

typescript - 将对象的数组/元组转换为由属性键入的对象的通用类型

转载 作者:行者123 更新时间:2023-12-04 04:11:49 27 4
gpt4 key购买 nike

假设我有以下内容:

type Field = {
_id: string;
value: string;
}

const fields = [
{ _id: 'a', value: '2' },
{ _id: 'b', value: '3' }
] as const;

我想定义一个 type ValueById<T extends readonly [...Field[]]>产生:

{
a: '2',
b: '3',
}

我已经部分到达了我想要的位置:

export type ValueById<T extends readonly [...Field[]]> = {
[Z in T[number]['_id']]: T[number]['value']
}

type NewType = ValueById<typeof fields>

但不幸的是,这会产生一种类型:

{
a: '2' | '3'
b: '2' | '3'
}

有没有办法缩小这里的值的类型?

最佳答案

首先我们需要提取array item type :

const fields = [
{ _id: 'a', value: '2' },
{ _id: 'b', value: '3' }
] as const;

type Field = typeof fields[number];
// {
// readonly _id: "a";
// readonly value: "2";
// } | {
// readonly _id: "b";
// readonly value: "3";
// }

现在我们可以使用 distributive conditional types 创建“id-value”对的并集

type IdValueUnion<T> = T extends Field ? { [Z in T['_id']]: T['value'] } : never;
// IdValueUnion<Field>
//
// {
// a: "2";
// } | {
// b: "3";
// }

我们非常接近,但我们需要 intersection instead of union :

type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
// UnionToIntersection<IdValueUnion<Field>>
// {
// a: "2";
// } & {
// b: "3";
// }

最后一步是通过将键重新映射到值来“压缩”交集:

export type Compact<T> = { [K in keyof T]: T[K] };

export type ValueById = Compact<UnionToIntersection<IdValueUnion<Field>>>;
// 🎉
// {
// a: "2";
// b: "3";
// }

let foo: ValueById = { a: '2', b: '3' }

Playground

关于typescript - 将对象的数组/元组转换为由属性键入的对象的通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61587568/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com