typescript 函数属性 vs 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39156315/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:47:51  来源:igfitidea点击:

Function property vs method

typescript

提问by Zev Spitz

What practical differences are there between defining an interface method:

定义接口方法之间有什么实际区别:

interface Foo {
    bar(): void;
}

and defining a property with a function type:

并定义具有函数类型的属性:

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

?

?

采纳答案by Ryan Cavanaugh

If these are the only declarations, these are identical.

如果这些是唯一的声明,则它们是相同的。

The only difference is that you can augmentthe 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

回答by Zev Spitz

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

还有另一个区别,readonly修饰符不能应用于方法。因此,无法阻止以下分配:

interface Foo {
    bar(): void;
}

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

If baris defined as a property, then the readonlymodifier can be applied to it:

如果bar被定义为一个属性,那么readonly修饰符可以应用于它:

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

preventing reassignment.

防止重新分配。

(Playground)

游乐场

回答by Nitzan Tomer

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:

原因可能与它如何编译成 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 barwhich is a callable function.
The difference is only that in Foo1Class2the barmethod is part of the prototype which can then be overriden by an extending class.

在这两种情况下,这些类之一的实例将具有一个名为bar可调用函数的属性。
所不同的只是,在Foo1Class2bar方法的原型然后其可通过延伸类被覆盖的一部分。

回答by tusharmath

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.

更严格的检查适用于所有函数类型,除了那些源自方法或构造函数声明的函数类型。专门排除方法以确保通用类和接口(例如 Array)继续主要协变相关。

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

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