Function property vs method

前端 未结 4 2017
春和景丽
春和景丽 2020-11-30 11:00

What practical differences are there between defining an interface method:

interface Foo {
    bar(): void;
}

and defining a property with

相关标签:
4条回答
  • 2020-11-30 11:24

    If these are the only declarations, these are identical.

    The only difference is that you can augment the first form in a second declaration to add new signatures:

    // Somewhere
    interface Foo {
      bar(): void;
    }
    
    // Somewhere else
    interface Foo {
      bar(s: number): void;
    }
    
    // Elsewhere
    let x: Foo = ...
    x.bar(32); // OK
    
    0 讨论(0)
  • 2020-11-30 11:24

    There is another difference, in that the readonly modifier cannot be applied to methods. Therefore, the following assignment cannot be prevented:

    interface Foo {
        bar(): void;
    }
    
    declare var x: Foo;
    x.bar = function () { };
    

    If bar is defined as a property, then the readonly modifier can be applied to it:

    interface Foo {
        readonly bar: () => void;
    }
    

    preventing reassignment.

    (Playground)

    0 讨论(0)
  • 2020-11-30 11:28

    It seems that the compiler doesn't seem to care, as all of these are valid:

    interface Foo1 {
        bar(): void;
    }
    
    class Foo1Class1 implements Foo1 {
        bar = () => { }
    }
    
    class Foo1Class2 implements Foo1 {
        bar() { }
    }
    
    interface Foo2 {
        bar: () => void;
    }
    
    class Foo2Class1 implements Foo2 {
        bar = () => { }
    }
    
    class Foo2Class2 implements Foo2 {
        bar() { }
    }
    

    (code in playground)

    The reason for that is probably to do with how that compiles into javascript:

    var Foo1Class1 = (function () {
        function Foo1Class1() {
            this.bar = function () { };
        }
        return Foo1Class1;
    }());
    var Foo1Class2 = (function () {
        function Foo1Class2() {
        }
        Foo1Class2.prototype.bar = function () { };
        return Foo1Class2;
    }());
    

    In both cases an instance of one of those classes will have a property named bar which is a callable function.
    The difference is only that in Foo1Class2 the bar method is part of the prototype which can then be overriden by an extending class.

    0 讨论(0)
  • 2020-11-30 11:36

    The most critical difference is actually that using the property approach typescript actually checks contravariently for types. For Eg:

    type FProp<A> = {
      fork: (a: A) => void  
    }
    type FMeth<A> = {
      fork(a: A): void  
    }
    
    type Cat = {
      isPurring: boolean
    }
    
    type Dog = {
      isBarking: boolean
    }
    
    
    const dd = { fork: (a: Cat & Dog) => void 0 }
    
    const fa: FProp<Cat> = dd // will throw up
    const fb: FMeth<Cat> = dd // will not issue any error
    

    This is documented —

    The stricter checking applies to all function types, except those originating in method or constructor declarations. Methods are excluded specifically to ensure generic classes and interfaces (such as Array) continue to mostly relate covariantly.

    https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html

    0 讨论(0)
提交回复
热议问题