英文:
Deriving object type from array of objects
问题
给定这个类型:
type ItemMetadata = {
name: string;
valueType: "string" | "number" | "boolean";
};
我想构建一个参数数组:
const MyMetaDatas = [
{
name: "The String",
valueType: "string"
},
{
name: "The Number",
valueType: "number"
}
] as const satisfies readonly ItemMetadata[];
并且给定这个只读的 MyMetaDatas 数组,我想构建一个对象,如下所示:
const MyParameters = {
"The String": "string",
"The Number": "number"
}
我想将这个对象类型命名为一个带有一个参数的泛型,如 ParametersFor<T extends readonly ItemMetadata[]> = { ...TODO }
。
尝试 #1
/**
* 试图从 ItemMetadata 的 const 数组生成 { name: valueType } 映射对象
*/
type ItemParameters<T extends readonly ItemMetadata[]> = {
[K in T[number]["name"]]: T[number]["valueType"];
};
/**
* 不太好,因为 T[number]["valueType"] 查看数组中的所有项,它会生成所有选项的 OR 类型...
type MyParams = {
"The String": "string" | "number" | "boolean";
"The Number": "string" | "number" | "boolean";
}
*/
type MyParams = ItemParameters<typeof MyMetaDatas>;
这确实正确地生成了对象的左侧,但右侧的 T[number]["valueType"]
查看了数组中的所有项,它会生成所有选项的 OR 类型。
尝试 #2
尝试了多种方法,得到了这个结果。这不会生成一个对象,而是生成一个包含一个键(name)和一个值(valueType)的元组。
type ParamsUsingSingle<T extends readonly ItemMetadata[]> = {
[K in keyof T]: {
[TName in T[K]["name"]]: T[K]["valueType"];
}
};
type MyParamsUsingSingle = ParamsUsingSingle<typeof MyMetaDatas>;
/**
* 接近,但现在我需要以某种方式将它们合并... 或者扁平化
*/
const x: MyParamsUsingSingle = [
{
"The String": "string"
},
{
"The Number": "number",
}
]
但现在我需要以某种方式将它们合并...
你能帮我解决这个任务吗?
英文:
Given this type:
type ItemMetadata = {
name: string;
valueType: "string" | "number" | "boolean";
};
I want to construct an array of parameters
const MyMetaDatas = [
{
name: "The String",
valueType: "string"
},
{
name: "The Number",
valueType: "number"
}
] as const satisfies readonly ItemMetadata[];
And given this - readonly MyMetaDatas array, I would like to consturct an object which looks like this
const MyParameters = {
"The String": "string",
"The Number": "number"
}
And I want to "type" this object type as a generic with 1 parameter - typeof MyMetadatas
- e.g. ParametersFor<T extends readonly ItemMetadata[]> = { ...TODO }
Attempt #1
/**
* Attempt on generating { name: valueType } map object, from const array of ItemMetadata
*/
type ItemParameters<T extends readonly ItemMetadata[]> = {
[K in T[number]["name"]]: T[number]["valueType"];
};
/**
* Not nice because T[number]["valueType"] looks at all of the items in the array
type MyParams = {
"The String": "string" | "number" | "boolean";
"The Number": "string" | "number" | "boolean";
}
*/
type MyParams = ItemParameters<typeof MyMetaDatas>;
This does procudce the left side of the object correctly, but T[number]
at the right side looks at the all of the items in the array, it produces OR types of all of the options...
Attempt #2
Tried multiple things, came up with this. This does not produce object, it produces a tuple of ojbects, where there is only one key - [name], and one value - [valueType].
type ParamsUsingSingle<T extends readonly ItemMetadata[]> = {
[K in keyof T]: {
[TName in T[K]["name"]]: T[K]["valueType"];
}
};
type MyParamsUsingSingle = ParamsUsingSingle<typeof MyMetaDatas>;
/**
* Close but now I would have to merge them into a signle object somehow.. Or to Flatten
*/
const x: MyParamsUsingSingle = [
{
"The String": "string"
},
{
"The Number": "number",
}
]
But now I need to merge them somehow...
Can anyone help me with this task?
Here are my numberous attempts in Typescript playground
答案1
得分: 1
你在你的第一次尝试中方向是正确的,但是你不应该只写 T[number]['valueType']
,因为它会给出所有可能性的联合类型。相反,你应该使用key remapping:
type GetParameters<T extends readonly ItemMetadata[]> = {
[K in T[number] as K["name"]]: K["valueType"];
};
用法:
// type Params = {
// "The String": "string";
// "The Number": "number";
// }
type Params = GetParameters<typeof MyMetaDatas>
英文:
You are in the right direction with your first attempt, however, you shouldn't just write T[number]['valueType']
, since it will give a union of all possibilities. Instead, you should use key remapping:
type GetParameters<T extends readonly ItemMetadata[]> = {
[K in T[number] as K["name"]]: K["valueType"];
};
Usage:
// type Params = {
// "The String": "string";
// "The Number": "number";
// }
type Params = GetParameters<typeof MyMetaDatas>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论