11

What is the difference between the type inference of foo1 and foo2 in the code given below:

interface myInterface {
    foo1(args: string): void;
    foo2: (args: string) => void;
}

Is type inference different for both? Also when to use which one?

vendettacbs
  • 159
  • 1
  • 9

2 Answers2

15

In interfaces, there is almost no difference. You can mix and match both styles, according to your preferences:

interface myInterface {
    foo1(args: string): void;
    foo2: (args: string) => void;
}

class C implements myInterface {
    foo1: (args: string) => void = (args) => {

    }

    foo2(args: string) {

    }
}

Also, both are completely interchangeable at runtime:

declare const i: myInterface;

const c = new C;

// no errors
c.foo1 = i.foo2;
i.foo1 = c.foo2;
c.foo2 = i.foo1;
i.foo2 = c.foo1;

There is one difference affecting type inference: --strictFunctionTypes flag does not apply to methods, so in strict mode methods and function properties have different compatibility rules when their argument and return types are not identical.

Another difference is that you can declare property read-only, to prevent assigning to it. You can't do that with a method (but still, you can declare another type with Readonly<myInterface> which will have all properties and methods read-only).

interface myInterface {
    foo1(args: string): void;
    readonly foo2: (args: string) => void;
}

i.foo2 = c.foo1; // this is an error now

However, in classes, they are different, probably because methods are defined on class prototype objects at runtime, but properties are initialized in the code generated for the constructor, so it's impossible to override property with a method:

class C2 extends C {

    foo1(args: string) { // error:  Class 'C' defines instance member property 'foo1',
                        // but extended class 'C2' defines it as instance member function.

    }

    foo2: (args: string) => void = (args) => { // Ok

    }

}
artem
  • 46,476
  • 8
  • 74
  • 78
  • It is also worth mentioning that arrow functions are a new concept in JavaScript (introduced in [ES6](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Functions/Arrow_functions), exactly), and that they came from [CoffeeScript](https://coffeescript.org/#fat-arrow). – Major Sam Feb 26 '19 at 14:35
  • 2
    I'd say that arrow/non-arrow function distinction does not apply if the function does not have a body. It's meaningful for function implementation only, and the question is about the interface. Whether function is bound with particular `this` or not is not part of its type (as seen from caller side, see [this parameter](https://www.typescriptlang.org/docs/handbook/functions.html#this-parameters)) in TypeScript. – artem Feb 26 '19 at 15:13
1

Although both definitions are the same on the type level, arrow functions as class properties are not interchangeable with methods in runtime.

In short, methods are inherited while class property fields are not. See this answer for more details.

Karol Majewski
  • 23,596
  • 8
  • 44
  • 53