Issue
I need some help with typescript generic typing. My aim is to do something like the one as follows. The function in the end should use first parameter index name to create new type Record<Key, Attributes[Key]> but the keys should be Picked from the array of keys.
Full code:
type IndexColumns<
I extends string,
Attrs extends Record<string, any>
> = Record<I, Array<keyof Attrs>>;
type CarIndexes = 'brand_model' | 'brand_category';
interface ICars {
brand: 'skoda' | 'ford' | 'volvo';
category: 'family' | 'off-road' | 'racing';
model: string;
}
const carIndexColumns: IndexColumns<CarIndexes, ICars> = {
brand_category: ['brand', 'category'],
brand_model: ['brand', 'model'],
}
// Find car by brand/model - correct
const requiredCar1 = findCarByIndex(
{
index: 'brand_model', // this one is easy
},
{
brand: 'skoda',
model: 'octavia',
}
);
// Find car by brand/category - incorrect
const requiredCar2 = findCarByIndex(
{
index: 'brand_category',
},
{ // this is my challenge
brand: 'ford',
category: 'racing',
model: 'mondeo', // incorrect - should not be here, not listed in brand_category: ['brand', 'category'],
}
);
// Find car by brand/category - incorrect
const requiredCar2 = findCarByIndex(
{
index: 'brand_model',
},
{ // incorrect - missing 'model' which is listed in brand_model: ['brand', 'model'],
brand: 'ford',
}
);
I've spent a lot of time in testing reading. Even ChatGPT is not successful and it looks like a simple task to me.
Anybody here to give me a helping hand?
Thank you
Solution
The first change I would make is to use satisfies
instead of a type assertion, so you don't lose the type information there:
const carIndexColumns = {
brand_category: ["brand", "category"],
brand_model: ["brand", "model"],
} satisfies IndexColumns<CarIndexes, ICars>;
Then you could write findCarByIndex
as follows:
declare function findCarByIndex<Index extends CarIndexes>(
filter: { index: Index },
arg: { [K in (typeof carIndexColumns)[Index][number]]: ICars[K] },
): void; /* or whatever return type */
We can "store" the given index and then look up the properties with it. Finally, we map the properties to the correct type from ICars
.
Answered By - merryweather
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.