Utilizing mapped tuples allows for the transformation of property tuples into type tuples, which can then serve as arguments for a callback function. This ensures that the callback function has a maximum number of parameters equal to the items in the dependentProperties
tuple. It does not mandate specifying all arguments (following TypeScript's definition of type compatibility for functions).
type Data = {
mortgage: {
purchasePrice: number,
investiture: number,
ownFunds: number,
otherProp: string
}
}
type MapTuple<T, K extends keyof T, NK extends Array<keyof T[K]>> = {
[P in keyof NK]: NK[P] extends keyof T[K] ? T[K][NK[P]] : never
}
class Test {
public addBusinessRule<K extends keyof Data, NK extends Array<keyof Data[K]>>(targetProperty: K,
dependentProperties: NK | [], // Allow compiler to infer tuple types
callback: (...a: MapTuple<Data, K, NK>) => void): void {
// some logic...
//callback(..dependentProperties)
};
public m() {
this.addBusinessRule('mortgage',
['purchasePrice', 'investiture', 'ownFunds', 'otherProp'],
(purchase, investiture, ownFunds, op) => { // parameter types inferred from Data type
});
}
}
The key element is the MapTuple
type. This type leverages mapped types, now supporting tuples and arrays since version 3.1 (check out this PR). Each property in the tuple NK
is matched with its corresponding type in T[K]
using a conditional type due to an inherent TypeScript limitation.
If only parameter count verification is desired without enforcing specific types (although it could degrade API usability), consider the following approach:
type MapTuple<NK extends Array<any>> = {
[P in keyof NK]: any
}
class Test {
public addBusinessRule<NK extends Array<string>>(targetProperty: string,
dependentProperties: NK | [], // Allow compiler to infer tuple types
callback: (...a: MapTuple<NK>) => void): void {
// some logic...
//callback(..dependentProperties)
};
public m() {
this.addBusinessRule('mortgage',
['purchasePrice', 'investiture', 'ownFunds', 'otherProp'],
(purchase, investiture, ownFunds, op) => { // all parameters are of type any
});
}
}