I have a TypeScript tuple of objects where all of them have the property name
.
type components = [
{
name: "fruit";
color: string;
},
{
name: "car";
speed: number;
brand: string;
}
];
I want to create a helper type to which I will pass the tuple type and it will convert it to the following
type wanted = {
fruit: {
name: "fruit";
color: string;
},
car: {
name: "car";
speed: number;
brand: string;
}
};
I tried this type
type tupleToObject<T extends any[]> = {
[K in components[number]["name"]]: T[number];
};
So that I will then be able to do the following
const foo: tupleToObject<components> = {
fruit: {
name: "fruit",
color: "red"
},
car: {
name: "car",
speed: 5,
brand: "toyota"
}
}; // typescript is ok with this assignment
const color = foo.fruit.color; // but here got error in .color
But color
is underlined red and if I hover it says
Property 'color' does not exist on type '{ name: "fruit"; color: string; } | { name: "car"; speed: number; brand: string; }'.
Property 'color' does not exist on type '{ name: "car"; speed: number; brand: string; }'
Is this achievable with TypeScript?
CodePudding user response:
Your mapped type would need to look like this:
type TupleToObject<T extends any[]> = {
[K in T[number] as K["name"]]: K;
}
We map over each element K
of the union T[number]
and use key remapping to extract name
from the union element K
.
const foo: TupleToObject<Components> = {
fruit: {
name: "fruit",
color: "red"
},
car: {
name: "car",
speed: 5,
brand: "toyota"
}
}
const color = foo.fruit.color
// works fine now