【问题标题】:TypeScript, what are call signature of an object literal and how can they be used with generic types?TypeScript,什么是对象文字的调用签名以及它们如何与泛型类型一起使用?
【发布时间】:2018-08-04 15:33:52
【问题描述】:

我正在阅读TypeScript documentation 的这一部分,在泛型类型部分下,以下两个被声明为等效:

代码示例 1

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: <T>(arg: T) => T = identity;

代码示例 2

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: {<T>(arg: T): T} = identity;

文档指出这是可能的,原因如下。

我们也可以将泛型类型写成对象字面量类型的调用签名

尽管有这一行,我仍然在努力理解这两者是如何等价的,是否有任何进一步的文档或解释来说明“对象文字类型的调用签名”的含义。

很抱歉,我无法给出进一步的解释,但我完全不知道这两者是如何等价的,对我来说,第二种类型定义表明 myIdentity 应该是一个对象?

谢谢。

【问题讨论】:

    标签: javascript typescript object generics object-literal


    【解决方案1】:

    函数可以具有属性,这就是对象字面量语法的用途:它允许定义调用签名和附加属性。您的两个示例是等效的,因为第二个示例没有在对象文字上定义其他属性。您可以在hybrid types 部分阅读更多内容。

    此外,对象字面量允许为函数重载定义多个调用签名。你可以用Object.assign创建这样一个接口的对象:

    interface Foo {
        (x: string): number,
        (x: number): string,
        bar: Array<any>,
    }
    
    const foo: Foo = Object.assign(function (x: any) {
        if (typeof x === 'string') {
            return parseInt(x);
        } else {
            return x.toString();
        }
    }, {
        bar: []
    });
    

    【讨论】:

      【解决方案2】:

      这是因为 Function 在 JavaScript 中也是一个对象。

      考虑以下几点:

      function foo() { return 'foo' }
      
      // vs
      
      const foo = Object.assign(
        function () { return 'foo' },
        {}
      )
      

      TypeScript 只是遵循 JavaScript 中的可能性。

      【讨论】:

        【解决方案3】:

        当我阅读 typescript 手册中的这个例子时,我也有同样的困惑。

        现在我是这样理解的,但不是很确定:

        interface MyFunc {
            (arg: string): string //define a function by a call signature
        }
        
        let myIdentity: MyFunc
        let myIdentity2: { 
            (arg: string): string //here is the body of MyFunc, the call signature
        } //the total is a call signature in an object literal type
        
        myIdentity = identity
        myIdentity2 = identity
        

        所以有两种函数定义格式:

        interface MyFunc {
            (arg: string): string //a call signature
            funcName: (arg: string) => string //express of function in object literal
        }
        

        【讨论】:

          【解决方案4】:

          按照 TypeScript 官方手册introduced(v3.7)

          为了用接口描述函数类型,我们给接口一个调用签名。这就像一个只给出参数列表和返回类型的函数声明。

          interface SearchFunc {
              (source: string, subString: string): boolean;
          }
          

          你会发现接口正是这样描述函数类型的,即“对象字面量”风格。

          PS:我在浏览 TypeScript 官方手册时遇到了同样的问题。当我查看这个 SO 问题时,所有答案都指的是混合类型部分,我在其中没有找到我的答案......它源于 Function-Types 部分。

          【讨论】:

            【解决方案5】:

            其他答案暗示了这一点,但可能需要明确。简而言之,第二个例子是函数和对象的混合类型。

            https://www.typescriptlang.org/docs/handbook/interfaces.html#hybrid-types

            定义一个接口,如果你给它一个名为“(...)”的属性,括号没有名字,这意味着你的接口可以应用于函数。可以说,接口“是”函数的接口。如果您添加其他命名属性,则会出现混合部分,以强调其作为对象的状态。

            对于某些读者来说,在修补此信息后,其他答案(很棒)可能更有意义。

            【讨论】:

              猜你喜欢
              • 2011-05-14
              • 2017-07-25
              • 2015-06-26
              • 2018-10-06
              • 2011-02-18
              • 2015-09-11
              • 2017-08-04
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多