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

tom*_*hes 8 javascript generics object object-literal typescript

我正在阅读TypeScript文档的这一部分,在“通用类型”部分下,以下两个声明是等效的:

代码样本1

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

let myIdentity: <T>(arg: T) => T = identity;
Run Code Online (Sandbox Code Playgroud)

代码样本2

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

let myIdentity: {<T>(arg: T): T} = identity;
Run Code Online (Sandbox Code Playgroud)

文档指出,由于以下原因,这是可能的。

我们还可以将泛型写为对象文字类型的调用签名

尽管有这句话,我仍在努力理解两者的等效性,是否有进一步的文档或说明“对象文字类型的调用签名”的含义。

对不起,我无法给出进一步的解释,但是我对两者的等效性完全是空白,对我来说第二种类型定义指出myIdentity应该是一个对象?

谢谢。

dav*_*avo 7

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

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

https://www.typescriptlang.org/docs/handbook/2/functions.html#call-signatures

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

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


小智 7

根据TypeScript官方手册介绍(v3.7)

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

interface SearchFunc {
    (source: string, subString: string): boolean;
}
Run Code Online (Sandbox Code Playgroud)

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

PS:我在浏览 TypeScript 官方手册时也有同样的问题。当我研究这个问题时,所有答案都指的是混合类型部分,其中我没有找到我的答案......它源于函数类型部分。


uni*_*nal 6

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

考虑以下:

function foo() { return 'foo' }

// vs

const foo = Object.assign(
  function () { return 'foo' },
  {}
)
Run Code Online (Sandbox Code Playgroud)

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


Tao*_*Tao 6

函数可以具有属性,这就是对象文字语法所针对的:它允许定义调用签名和其他属性。您的两个示例是等效的,因为第二个示例未在对象文字上定义其他属性。您可以在有关混合类型的部分中阅读更多内容。

此外,对象文字允许为函数重载定义多个调用签名。您可以使用以下方法创建此类接口的对象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: []
});
Run Code Online (Sandbox Code Playgroud)


hyy*_*010 5

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

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

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
Run Code Online (Sandbox Code Playgroud)

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

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