Reputation: 6269
Variadic tuple types allow us to provide the caller of a function, a tuple return type driven by the tuple supplied to the function like so:
function makeArrayAsConstItems<T extends readonly any[]>(...arr: [...T]): {[K in keyof T]: {item: T[K]} } {
return arr.map(item => ({ item })) as any;
}
const arrayAsConstItems = makeArrayAsConstItems('cfgh', 1, new Date());
// this is the type
const arrayAsConstItems: [{
item: string;
}, {
item: number;
}, {
item: Date;
}]
Now consider we want to do two more things:
Data<TypeOfData>
Data<TypeOfData>
; so use TypeOfData
essentiallyinterface Data<TypeOfData = unknown> {
data: TypeOfData;
}
function makeArrayAsConstItemsForDataTypesOnly<T extends readonly Data[]>(...arr: [...T]): {[K in keyof T]: {item: T[K]} } {
return arr.map(item => ({ item })) as any;
}
const arrayAsConstItemsForDataTypesOnly = makeArrayAsConstItemsForDataTypesOnly(
{ data: 'cfgh' },
{ data: 1 },
{ data: new Date() }
)
What would we need to do for arrayAsConstItemsForDataTypesOnly
to have the same type as arrayAsConstItems
?
At present the type is:
const arrayAsConstItemsForDataTypesOnly: [{
item: {
data: string;
};
}, {
item: {
data: number;
};
}, {
item: {
data: Date;
};
}]
And we desire it to be:
const arrayAsConstItemsForDataTypesOnly: [{
item: string;
}, {
item: number;
}, {
item: Date;
}]
This is @A_blop's suggestion:
function makeArrayAsConstItemsForDataTypesOnly<T extends readonly Data[]>(...arr: [...T]): {[K in keyof T]: {item: Extract<T[K], Data>["data"]} } {
return arr.map(item => ({ item })) as any;
}
Upvotes: 1
Views: 159
Reputation: 862
We can do that by utilizing lookup types in combination with the Extract
utility type:
function fn<T extends readonly Data[]>(...arr: [...T]):
{ [K in keyof T]: { item: Extract<T[K], Data>["data"] } } {/* impl */}
const arrayAsConstItemsForDataTypesOnly = fn(
{ data: 'cfgh' },
{ data: 1 },
{ data: new Date() }
)
/*
[{
item: string;
}, {
item: number;
}, {
item: Date;
}]
*/
As TypeScript cannot resolve T[K]
further, we need to first convince it again, that the resulting type has a data
property accessible via lookup operator. This is done by Extract
.
Upvotes: 3