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:
- Narrow the items that can be supplied in each array element to be a type of
Data<TypeOfData> - Extract the type we're going to be returning from
Data<TypeOfData>; so useTypeOfDataessentially
interface 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;
}
{[K in keyof T]: {item: Extract<T[K], Data>["data"]} }?