定义接口方法之间存在哪些实际差异:
interface Foo {
bar(): void;
}
并使用函数类型定义属性:
interface Foo {
bar: () => void;
}
答案 0 :(得分:14)
还有另一个区别,因为\/[^\/]+\/\d{4}\/\d{2}\/\d{2}\/[^\/]+
修饰符无法应用于方法。因此,无法阻止以下分配:
readonly
如果将interface Foo {
bar(): void;
}
declare var x: Foo;
x.bar = function () { };
定义为属性,则可以对其应用bar
修饰符:
readonly
阻止重新分配。
答案 1 :(得分:13)
如果这些是唯一的声明,则它们是相同的。
唯一的区别是你可以在第二个声明中扩充第一个表单来添加新签名:
// Somewhere
interface Foo {
bar(): void;
}
// Somewhere else
interface Foo {
bar(s: number): void;
}
// Elsewhere
let x: Foo = ...
x.bar(32); // OK
答案 2 :(得分:6)
似乎编译器似乎并不关心,因为所有这些都是有效的:
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() { }
}
原因可能与编译为javascript的方式有关:
var Foo1Class1 = (function () {
function Foo1Class1() {
this.bar = function () { };
}
return Foo1Class1;
}());
var Foo1Class2 = (function () {
function Foo1Class2() {
}
Foo1Class2.prototype.bar = function () { };
return Foo1Class2;
}());
在这两种情况下,其中一个类的实例将具有名为bar
的属性,该属性是可调用的函数。
不同之处仅在于Foo1Class2
bar
方法是原型的一部分,然后可以通过扩展类重写。
答案 3 :(得分:1)
最关键的区别实际上是使用属性方法打字稿实际上是对类型进行了相反检查。例如:
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
已记录-
更严格的检查适用于所有功能类型,但那些功能类型除外 源于方法或构造函数声明。方法是 专门排除以确保通用类和接口(例如 如Array)继续主要是协变的。
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html