TypeScript,啥是对象文字的调用签名以及它们如何与泛型类型一起使用?

Posted

技术标签:

【中文标题】TypeScript,啥是对象文字的调用签名以及它们如何与泛型类型一起使用?【英文标题】: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 应该是一个对象?

谢谢。

【问题讨论】:

【参考方案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】:

这是因为 Functionjavascript 中也是一个对象。

考虑以下几点:

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

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

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

【讨论】:

以上是关于TypeScript,啥是对象文字的调用签名以及它们如何与泛型类型一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

具有多个调用签名的 TypeScript 接口

Typescript中的“无法调用类型缺少调用签名的表达式”?

route.component 没有任何构造或调用签名 - 使用 TypeScript 的 React Router

Typescript 编译器错误 - 提供的参数与调用目标的任何签名都不匹配

TypeScript 回调没有在其签名中完全实例化类

究竟啥是 getattr() 以及如何使用它?