3

Is it possible to expand every method of parent interface in child interface?

interface IFoo {
    methodOne(a: any)
    methodTwo(a: any)
}

interface IBar extends IFoo {
   //make IBar have all methods of Ifoo, but make it take additionlal arguments
   //as in methodOne(a: any, b: any, c: any)
   // and methodTwo(a: any, b: any, c: any)
}

is there a way to achieve this, without repeating all code from IFoo?

Anarion
  • 2,406
  • 3
  • 28
  • 42
  • 2
    A solution that does this without redefining all function is possible in 2.8 unsing conditional types, see this answer for inspiration, I will add an answer later if no one else does https://stackoverflow.com/questions/49420657/how-to-remove-properties-and-promisify-method-via-mapped-type-in-typescript/49421381#49421381 – Titian Cernicova-Dragomir Mar 25 '18 at 16:48

2 Answers2

4

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

Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
2

You can extend an interface and add optional parameters:

interface IBar extends IFoo {
    methodOne(a: any, b?: any, c?: any);
}

The ? makes the parameters optional. But you have to define them with additional parameters.

David Ibl
  • 901
  • 5
  • 13
  • Yeah, that's the way I know of. I thought that there might be a way to shorten the code, since all methods of child interface have the same parameters added. – Anarion Mar 25 '18 at 16:42