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

时间:2018-02-24 20:14:37

标签: javascript typescript object generics object-literal

我正在阅读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;

文档说明这可能是由于以下原因。

  

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

尽管我仍然在努力理解这两者是如何相同的,但是还有任何进一步的文档或解释它意味着对象文字类型的呼叫签名&#39;。

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

感谢。

6 个答案:

答案 0 :(得分:3)

函数可以具有属性,这就是对象文字语法的用途:它允许定义调用签名和其他属性。您的两个示例是等效的,因为第二个示例未在对象文字上定义其他属性。您可以在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: []
});

答案 1 :(得分:2)

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

请考虑以下事项:

function foo() { return 'foo' }

// vs

const foo = Object.assign(
  function () { reutrn 'foo' },
  {}
)

TypeScript遵循JavaScript中的可能性。

答案 2 :(得分:2)

作为TypeScript官方手册introduced(v3.7)

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

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

您会发现接口正是以这种方式描述函数类型的,即“对象文字”样式。

PS:我正在浏览TypeScript官方手册,并且有相同的问题。当我调查这个SO问题时,所有答案都参考了混合类型部分,在该部分中找不到我的答案...它起源于Function-Types部分。

答案 3 :(得分:1)

当我在打字稿手册中阅读此示例时,我也有完全相同的困惑。

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

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 :(得分:0)

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

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

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

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

答案 5 :(得分:0)

好的,这就是事情。函数是一流的对象。

假设您要键入一个名为myIdentity的函数,可以通过多种方法进行。

一种方法可能更熟悉

const myIdentity = (x: string, y:string):string => {
    return x + y
}

或者您可以选择更冗长的路线

const myIdentity = {(x: string, y:string):string} = (x, y) => x + y

对于更冗长的方法,我们基本上要做的是定义myIdentity对象的调用签名的类型,在这种情况下,这相当于仅在myIdentity函数上创建和定义一个类型。