TypeScript调用签名

TypeScript调用签名,函数在本质上是一个对象,但特殊的地方在于函数是可调用的对象。因此,可以使用对象类型来表示函数类型。若在对象类型中定义了调用签名类型成员,那么我们称该对象类型为函数类型。调用签名的语法如下所示:

{
    (ParameterList): Type
}

在该语法中,ParameterList表示函数形式参数列表类型,Type表示函数返回值类型,两者都是可选的。

下例中,我们使用对象类型字面量和调用签名定义了一个函数类型,该函数类型接受两个number类型的参数,并返回number类型的值:

let add: { (x: number, y: number): number };

add = function (x: number, y: number): number {
   return x + y;
};

实际上,酷客教程上节介绍的函数类型字面量完全等同于仅包含一个类型成员并且是调用签名类型成员的对象类型字面量。换句话说,函数类型字面量是仅包含单个调用签名的对象类型字面量的简写形式,如下所示:

{ ( ParameterList ): Type }

// 简写为:

( ParameterList ) => Type

例如,“Math.abs()”是一个内置函数,它接受一个数字参数并返回该参数的绝对值。下面,我们分别使用函数类型字面量和带有调用签名的对象类型字面量来定义“Math.abs()”函数的类型:

const abs0: (x: number) => number = Math.abs;

const abs1: { (x: number): number } = Math.abs;

abs0(-1) === abs1(-1);  // true

函数类型字面量的优点是简洁,而对象类型字面量的优点是具有更强的类型表达能力。我们知道函数是一种对象,因此函数可以拥有自己的属性。下例中,函数f除了可以被调用以外,还提供了一个version属性:

function f(x: number) {
   console.log(x);
}

f.version = '1.0';

f(1); // 1
f.version;   // '1.0'

若使用函数类型字面量,则无法描述string类型的version属性,因此也就无法准确地描述函数f的类型。示例如下:

function f(x: number) {
   console.log(x);
}
f.version = '1.0';

let foo: (x: number) => void = f;

const version = foo.version;
//        ~~~~~~~
//        编译错误:'(x: number) => void' 类型
//        上不存在 'version' 属性

在这种情况下,我们可以使用带有调用签名的对象类型字面量来准确地描述函数f的类型。示例如下:

function f(x: number) {
   console.log(x);
}
f.version = '1.0';

let foo: { (x: number): void; version: string } = f;

const version = foo.version;  // string类型

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!