You have the option to utilize a syntax similar to this:
function customizedFunction<T extends any[]>(...items: {
[K in keyof T]: T[K] & { description: (v: Omit<T[K], 'description'>) => void }
}) {}
In this case, a mapped type is employed to iterate over each element in items
. The representation of T[K]
always reflects the current element, enabling us to intersect it with the function object.
// valid
customizedFunction({
name: "",
description: (v: { name: string }) => {}
}, {
count: 0,
description: (v: { count: number }) => {}
})
// invalid
customizedFunction({
name: 0,
description: (v: { name: string }) => {} /*
~~~~ Types of property 'name' are incompatible
*/
}, {
count: 0,
description: (v: { count: number }) => {}
})
When implementing the function, it is advisable to encapsulate all the intricate generic aspects in an overload and adopt a simpler signature for the implementing function.
function implementationFunc<T extends any[]>(...items: {
[K in keyof T]: T[K] & { description: (v: Omit<T[K], 'description'>) => void }
}): void
function implementationFunc(...items: ({ description: (arg: object) => void } & Record<string, any>)[]) {
for (const item of items) {
item.description({})
}
}
Interactive Tool