【问题标题】:How do I represent a return type in a Typescript interface file?如何在 Typescript 接口文件中表示返回类型?
【发布时间】:2016-03-22 11:23:21
【问题描述】:

以下代码有什么区别:

changeName(): ng.IPromise<any>;

changeName: () => ng.IPromise<any>;

我知道一个是返回类型,但我对第一个感到困惑。

这是函数体:

changeName = (): ng.IPromise<any> => {
        var self = this;
        self.chnAction = "PREFERENCES.CHANGE_NAME.SUBMITTING_BUTTON_TEXT";
        self.chnErrorMessage = null;
        return self.uss.changeName(
            self.chnNewFirstName,
            self.chnNewLastName)
            .then(
            (response: ng.IHttpPromiseCallbackArg<any>): any => {
                self.chnAction = "PREFERENCES.CHANGE_NAME.SUBMITTED_BUTTON_TEXT";
                self.chnNewFirstName = '';
                self.chnNewLastName = '';
                self.chnErrorMessage = null;
                self.logout();
                return this.$state.go('home.auth', { content: 'change_name_success' });
            },
            (error: ng.IHttpPromiseCallbackArg<any>): ng.IPromise<any> => {
                if (error.status === 500) {
                    self.chnErrorMessage = 'AUTH_SERVICE.UNABLE_TO_CONTACT_SERVER';
                } else {
                    var errors: string[] = [];
                    Object.keys(error.data.modelState).forEach((key) => {
                        errors.push.apply(errors, error.data.modelState[key]);
                    });
                    self.chnErrorMessage = errors[0];
                    self.chnErrorMessages = errors;
                    self.chnAction = "PREFERENCES.CHANGE_NAME.SUBMIT_BUTTON_TEXT";
                }
                return this.$q.reject(error);
            });
    };

【问题讨论】:

  • 第一个是接口的方法,第二个是接口的属性(Function类型)
  • 您现在可以在整个过程中使用this 而不是self,因为this 将携带任何=&gt; 箭头函数。此外,接口上的方法和函数属性之间没有区别(请参阅我的回答)。

标签: javascript typescript


【解决方案1】:

根本区别在于:

  • changeName(): ng.IPromise&lt;any&gt;; 代表一个方法
  • changeName: () =&gt; ng.IPromise&lt;any&gt;; 代表一个属性,它可以容纳一个函数(这与 changeName = (): ng.IPromise&lt;any&gt; =&gt; { ... }; 匹配,因为它正在将一个函数分配给一个属性)。

因此,属性和方法之间的差异适用。这是一个例子:

interface MyInterface {
    myMethod(): string;
    myProperty: () => string;
}

class MyBaseClass implements MyInterface {
    myMethod() {
        return "string";
    }

    myProperty = () => "string";
}

class MyChildClass extends MyBaseClass {
    myMethod() {
        return super.myMethod();
    }

    myProperty = () => super.myProperty(); // error
}

有时使用箭头函数属性而不是方法的原因是因为分配给属性的箭头函数会保留this 的值,无论绑定到什么...

class MyClass {
    myMethod() {
        console.log(this);
    }

    myProperty = () => console.log(this);
}

new MyClass().myMethod.call({});   // outputs {}
new MyClass().myProperty.call({}); // outputs the instance of MyClass

...因为this 的值保存在构造函数中...

var MyClass = (function () {
    function MyClass() {
        // captures this here
        var _this = this;
        // guaranteed to always use instance of class for `this`
        this.myProperty = function () { return console.log(_this); };
    }
    MyClass.prototype.myMethod = function () {
        // not guarnateed to always use instance of class
        console.log(this);
    };
    return MyClass;
})();

旁注:您可以在 JS here 中阅读有关 .call 的信息。

【讨论】:

    【解决方案2】:

    界面上没有区别。这是一个使用两种表示法的接口(为了清楚起见,我们使用string 作为返回类型):

    interface MyInterface {
        foo(): string; // preferred
        bar: () => string;
    }
    

    这里,foo 是一个返回类型为string 的函数。而bar的类型也是一个返回类型为string的函数。第一个符号通常更清晰。以下对象与接口匹配:

    let x: MyInterface = {
        foo: () => "",
        bar: () => ""
    }
    

    上,一种表示法是将函数添加到原型中,而另一种表示法将其作为新实例的属性添加 (this.myFunc = ...)。这与在 JavaScript 中的效果完全相同(您几乎不需要将函数/方法添加为实例属性)。

    class MyClass {
        bar(): string { return ""; } // prototype, preferred
        foo = () => ""; // instance property
    }
    

    正如我们在下面看到的,这个类适合我们原来的界面,尽管我已经颠倒了foobar。因此,接口不会强加如何设置方法的实现细节。

    let y: MyInterface = new MyClass();
    

    请注意,类不是特殊类型——它实际上是一个接口加上一个实现。所以你可以像使用任何其他类型(无论是定义为接口还是类)一样使用MyClass

    let z: MyClass = {
        foo: () => "",
        bar: () => ""
    }
    

    就类型(这是接口定义的内容)而言,没有区别,但在类中使用时,符号会产生不同的实现。

    【讨论】:

      【解决方案3】:

      下面的代码有什么区别

      因为您没有添加更多代码来查看实际配置的内容。如我所见,您有两行代码:

      changeName(): ng.IPromise<any>;
      

      根据这段代码,人们可以理解它返回了 any 类型的承诺,可以是任何东西,object, string, array, number 等。

      因此可以说changeName() 将返回ng.IPromise 类型为&lt;any&gt;thing 的值。


      而另一行代码:

      changeName: () => ng.IPromise<any>;
      

      表示此函数将返回值ng.IPromise&lt;any&gt;thing。

      【讨论】:

      • 我更新了我的问题以显示该功能。我希望它更清楚。基于此,您能告诉我您认为我应该如何设置界面吗?
      【解决方案4】:

      最好显示整个代码示例。希望下面的例子能解释你的问题:

      class MyClass {
      
          changeName(): number {
              return 5;
          }
      
          changeName2 = ():number => {
              return 5;
          }
      }
      

      转译为:

      var MyClass = (function () {
          function MyClass() {
              this.changeName2 = function () {
                  return 5;
              };
          }
          MyClass.prototype.changeName = function () {
              return 5;
          };
          return MyClass;
      })();
      

      [Playground]

      这两个定义的区别在Declaring javascript object method in constructor function vs. in prototype中有深入的解释

      【讨论】:

      • 我添加了函数体,以便您查看它的外观。对不起,但我不太清楚你的意思。您可以根据功能本身看一下并告诉我吗?谢谢
      • @Sophia:我不确定我是否正确理解了您的问题,但我试图向您展示当您在操场上使用前者和后者定义时会发生什么。不同之处在于转译结果不同。出于您的目的,我想您可以将它们视为相同。
      猜你喜欢
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 2020-09-14
      • 2013-06-11
      • 2020-09-04
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      相关资源
      最近更新 更多