10

I've got the following code:

class A {
  constructor(public n: number) {}  

  defaultFn(a: number): number {
    return a + 1;
  }

  doStuff(callback?): number {
    return callback ? callback(this.n) : this.defaultFn(this.n);
  }
}

How can I tell TypeScript that the optional callback function passed to doStuff method should have the same signature as defaultFn method?

szimek
  • 6,404
  • 5
  • 32
  • 36

2 Answers2

10
interface Callback {
    (n:number):number;
}

class A {
    constructor(public n: number) { }

    public readonly defaultFn: Callback = (a: number): number => {
        return a + 1;
    }

    public doStuff(callback?: Callback): number {
        return callback ? callback(this.n) : this.defaultFn(this.n);
    }
}

You can also simply do this

doStuff(callback?: (n:number)=>number): number {
    return callback ? callback(this.n) : this.defaultFn(this.n);
}

Or combine with an interface

interface Callback {
    (n:number):number;
}

doStuff(callback?: Callback): number {
    return callback ? callback(this.n) : this.defaultFn(this.n);
}
smac89
  • 39,374
  • 15
  • 132
  • 179
  • Thanks! One question though - do I have to repeat type definition for `defaultFn`? You wrote `defaultFn: Callback = (a: number): number` - isn't it redundant to specify `Callback` and `(a: number): number`? Can it be simplified if I rename parameter name form `a` to `n`, as it is declared in `Callback` interface? – szimek Nov 11 '17 at 20:08
  • @szimek oh yea you can definitely remove the type specification, and just make it a class method rather than a field. Renaming the parameter will not make it any different, it's just a name of a parameter, nothing more. – smac89 Nov 11 '17 at 20:13
  • @szimek the reason I used the type is to make it more obvious to the reader that `defaultFn` is the same type as the callback, also reduces compile time. That's the beauty of static typing. – smac89 Nov 11 '17 at 20:15
  • Thanks. When I paste your first example to TS playground it gives me syntax error, though it still generates JS code :/ What's the syntax to replace `defaultFn: Callback = (a: number): number` with something like `defaultFn: Callback`? In my real code this function accepts a few parameters, so I'd like to avoid repeating them if possible. – szimek Nov 11 '17 at 20:32
  • @szimek, my bad, it's been a while since I last used typescript, the code is now good. I was missing a `=>`. I also made it `readonly` so that it is obvious that the field is not to be modified – smac89 Nov 11 '17 at 20:38
4

One more option is to "query" type of defaultFn. In this case you won't need to maintain the type of callback manually:

class A {
    constructor(public n: number) {}  

    defaultFn(a: number): number {
        return a + 1;
    }

    doStuff(callback?: A['defaultFn']): number {
        return callback ? callback(this.n) : this.defaultFn(this.n);
    }
}

The result of A['deafultFn'] is (a: number) => number

Aleksey L.
  • 35,047
  • 10
  • 74
  • 84