在Typescript中声明一个委托类型

74

作为一个C#的开发者,我希望创建一个定义函数签名的数据类型。在C#中,这个数据类型是使用delegate声明的,如下所示:

delegate void Greeter (string message);

public class Foo
{
    public void SayHi (Greeter g) {
        g("Hi!");
    }
}

现在,我希望在Typescript中实现类似的功能。我知道Typescript没有委托类型,只有lambda表达式。我想到了以下代码:

class Foo {
    SayHi (greeter: (msg: String) => void) {
        greeter('Hi!');
    }
}

虽然这种方法可以工作,但我想重复使用方法签名 (msg:String) => void 几次,并认为创建自定义类型(如C#中的委托)会更清晰。

有什么想法吗?


可能是TypeScript中是否可能将强类型函数作为参数?的重复问题。 - WiredPrairie
5个回答

89
在TypeScript中,接口可以拥有调用签名。在您的示例中,您可以这样声明它:
interface Greeter {
    (message: string): void;
}

function sayHi(greeter: Greeter) {
    greeter('Hello!');
}

sayHi((msg) => console.log(msg)); // msg is inferred as string

1
虽然不完全相同,但这是我们最好的选择。我讨厌在各个地方声明接口,而匿名强类型函数应该可以胜任。 - Alwyn
1
不确定您的意思 - 您也可以拥有匿名函数类型。 - Ryan Cavanaugh
我想声明一个函数,该函数接受一个回调委托,例如在C#中使用的Func<string,int>。在TypeScript中如何声明它?使用lambda运算符来声明委托的实例而不是类型。类型是匿名委托Func<string,int>。相应的语法是什么? - Alwyn
11
好的,我会尽力进行翻译。请告诉我需要翻译的内容。 - Ryan Cavanaugh
如何声明并导出一个 Greeter 实例的函数,以便在不同文件中导入 greeter 函数时获得正确的智能感知? - Steven Liekens

52
你可以通过使用 类型别名 来创建类似委托的东西: type MyDelegate = (input: string) => void; 它定义了一个函数指针的类型名称,就像C#中的委托一样。下面的示例将其与通用类型参数结合使用:
type Predicate<T> = (item: T) => boolean;

export class List<T> extends Array<T> {
    constructor(...items: T[]){
        super();
        for(let i of items || []){
            this.push(i);
        }
    }
    public hasAny(predicate?: Predicate<T>): boolean {
        predicate = predicate || (i => true)
        for(let item of this) {
            if(predicate(item)) return true;
        }
        return false;
    }
}

5
这些被称为“类型别名”。 - Robert Koritnik

13

五年后,经历了许多个 TypeScript 版本后,我发现自己使用更简单的 type 定义来声明函数类型:

type Greeter = (msg: string) => void;
const someGreeter: Greeter = (msg: string) => `Hi there with ${msg}`;

2
请注意,第2行上的 ": string" 不是必需的;该类型可以根据分配给 "Greeter" 进行推断。 - TheRubberDuck

1

可调用表达式的类型定义(这是一个草稿,仅供人类阅读……不是BNF或任何正式的东西)

callableType: (paramsDef) => returnType

paramsDef:    MULTIPLE paramDef SEPARATED BY ,

paramDef:     EITHER   paramName: paramType
                  OR   optionalParamName?: paramTypeWhenDefined
                  OR   ...manyParamName: eachParamType[]

例子:

var func = something as ((...x: any[]) => any);

然后您可以:
var result = func("a", "b", 2);

0

我现在发布并使用@steelbreeze/delegate;与C#委托相比,它有一些限制,因为它是不可变的,但除此之外它运行良好(当调用时返回所有被调用函数的结果)。

它让你编写如下代码:

import { create as delegate } from "@steelbreeze/delegate";

function world(s: string) {
    console.log(s + " world");
}

const one = delegate(s => console.log(s + " Hello world"));
const two = delegate(s => console.log(s + " Hello"), world);

one("A");
two("B");

delegate(one, two)("C");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接