You can do this using mapped types and conditional types in typescript 2.8 (unreleased at the time of writing, should be released in March, currently in RC, you can get it via npm install -g typescript@rc
)
// Helper
type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
// Works for 3 parameters you can add more as needed, see link below for info
type AddParameters<T> =
T extends (a: infer A, b: infer B, c: infer C) => infer R ? (
IsValidArg<C> extends true ? (a: A, b: B, c: C, addedA: any, addedB: any) => R :
IsValidArg<B> extends true ? (a: A, b: B, addedA: any, addedB: any) => R :
IsValidArg<A> extends true ? (a: A, addedA: any, addedB: any) => R :
(addedA: any, addedB: any) => Promise<R>
) : never;
type InterfaceWithExtraParameters<T> = {
[P in keyof T ] : AddParameters<T[P]>
}
interface IFoo {
methodOne(a: string): string
methodTwo(a: number): number
}
type IBar = InterfaceWithExtraParameters<IFoo>;
// Equivalent to :
// type IBar = {
// methodOne: (a: string, addedA: any, addedB: any) => string;
// methodTwo: (a: number, addedA: any, addedB: any) => number;
// }
// Can be imelmented by a class
class BarImpl implements IBar {
methodOne(a: string, addedA: any, addedB: any): string{
return a;
}
methodTwo(a: number, addedA: any, addedB: any): number {
return a;
}
}
As you can see there is a lot of ceremony to get this done, you might be better off for simple single use cases to just redefine the methods, but it is up to you which route you choose.
To extend AddParameters
for more parameters see this answer