function vs property in interface

There are two ways to define a method in an interface.
interface Logger {
log: (message: string) => void;
}
interface Logger {
log(message: string): void;
}

Differences

  1. If the method is declared as a interface function, then it's possible for you to add more overload versions.
    interface Logger {
    log(message: string): void;
    }
    // In other places
    interface Logger {
    log(message: string, level: string): void;
    }
    Declaring method as a property, on the other hand, prevents you from duplicating the property declarations which have different types:
    interface Logger {
    log: (message: string) => void;
    }
    // Does not work
    interface Logger {
    log: (message: string, level: string) => void;
    }
  2. The readonly modifier only has effect with the property declaration.
    interface Person {
    firstName: string;
    lastName: string;
    readonly fullName: () => string;
    // Doesn't work
    // readonly fullName(): string;
    }
  3. TypeScript generates different output for a class that implements the interface methods.
    Assume that we have a class ConsoleLogger that simply logs the message in the Console window.
    For the first approach:
    interface Logger {
    log: (message: string) => void;
    }
    class ConsoleLogger implements Logger {
    log = (message: string) => {
    console.log(message);
    };
    }
    // Generated JavaScript code:
    //
    // class ConsoleLogger {
    // constructor() {
    // this.log = (message) => {
    // console.log(message);
    // };
    // }
    // }
    For the second approach:
    interface Logger {
    log(message: string): void;
    }
    class ConsoleLogger implements Logger {
    log(message: string) {
    console.log(message);
    }
    }
    // Generated JavaScript code:
    //
    // class ConsoleLogger {
    // log(message) {
    // console.log(message);
    // }
    // }
    Looking at the generated JavaScript codes, you'll see the different outputs.
    The first approach produces a property log in the constructor. It means that log will be created every time you create a new instance of class.
    While the second approach produces the log method, and it exists in all instances of class. The log method also is a member of class prototype, so we can extend the class to override the method if needed:
    class ConsoleLogger implements Logger {
    log(message: string) {
    console.log(message);
    }
    }
    class ConsoleLoggerWithColor extends ConsoleLogger {
    // Override the `log` method
    log(message: string) {
    // Display the message in white color and blue background area
    console.log('%c%s', 'color: white; background: blue', message);
    }
    }
    See the differences between declaring methods in class constructor and prototype for more details.