TypeScript:我可以为重载的函数签名提供类型别名吗?

时间:2017-08-15 13:13:55

标签: typescript

是否可以为重载的函数签名创建类型别名?

例如,我有一个像:

这样的函数
function whenChanged(scope: ng.IScope, fn: ()=>void): ()=>void;
function whenChanged(fn: ()=>void, truthy:any): ()=>void;
function whenChanged(a,b): ()=>void {
    //...
}

我想为重载的签名创建类型别名以节省重复,并在我需要描述此函数类型的其他地方使用。

我试过了:

type WC1 = (scope: ng.IScope, fn: ()=>void) => ()=>void;
type WC2 = (fn: ()=>void, truthy:any) => ()=>void;
type WhenChanged = WC1 | WC2;

const whenChanged: WhenChanged = (a,b) => {
    //...
};

但是试图使用这个函数,我得到一个错误,就是"无法调用一个类型缺少调用签名的表达式"。

我无法在文档中看到有关类型别名函数重载的任何内容。

3 个答案:

答案 0 :(得分:3)

由于您已经拥有whenChanged函数:

function whenChanged(scope: ng.IScope, fn: ()=>void): ()=>void;
function whenChanged(fn: ()=>void, truthy:any): ()=>void;
function whenChanged(a,b): ()=>void {
    //...
}

获取其类型的类型别名的最简单方法是使用typeof type query

type WhenChanged = typeof whenChanged;

创建类型别名的下一个最直接的方法是使用overloaded function signature(这就是你要找的):

type WhenChanged = {
  (scope: ng.IScope, fn: () => void): () => void;
  (fn: () => void, truthy: any): () => void;
}

(如果您将鼠标悬停在编辑器中的typeof定义上,则会在quickinfo中看到这一点。)请注意,如果您不在{39},则不需要使用interface ; t想要。

您可以做的下一件事情与您正在做的事情类似,但问题是,重载是交集,而不是 union 。它是两个签名:

type WC1 = (scope: ng.IScope, fn: ()=>void) => ()=>void;
type WC2 = (fn: ()=>void, truthy:any) => ()=>void;
type WhenChanged = WC1 & WC2; // and, not or

小心intersections of function signatures are not commutative,特别是因为它们代表了重载。这意味着以下类型在技术上并不相同:

type NotWhenChanged = WC2 & WC1; // different type

因为重载决策将以不同的顺序发生。

请注意,您无法调用WC1 | WC2类型的函数,因为调用签名不同,编译器无法判断该函数是WC1还是WC2

好的,你去吧。希望能帮助到你;祝你好运!

答案 1 :(得分:1)

在一些游戏之后,事实证明答案是(至少部分地)使用界面。这似乎有效:

interface WhenChanged {
    (scope: ng.IScope, fn: ()=>void): ()=>void
    (fn: ()=>void, truthy:any): ()=>void
}

const whenChanged: WhenChanged = (a,b) => {
    //...
};

答案 2 :(得分:0)

"无法调用类型缺少调用签名的表达式"表示类型的并集是不可调用的,您必须选择一种类型或另一种类型。

问题是,在示例中,您为ab定义了类型,因此编译器无法分辨WC1和{{1}中的哪一个实际上正在被使用。如果您更改WC2的定义:

whenChanged

现在编译器知道它可以将const whenChanged: WhenChanged = (a: ng.IScope, b: ()=>void) => { return b; }; 的类型限制为whenChanged,以便您可以安全地调用它。

如果你有一个变量而不是const而WC1可能是whenChangedWC1,编译器无法告诉你那么你将不得不使用某种类型的断言在调用之前将类型限制为一个或另一个:

WC2

或:

(whenChanged as WC1)(some_scope, some_fn);

你不能做的是从(whenChanged as WC2)(some_fn, some_truthy); 中找出它所包含的类型,以便用适当的参数调用它。您必须从其他地方获取该信息。