在 Typescript 中声明一个委托类型

Posted

技术标签:

【中文标题】在 Typescript 中声明一个委托类型【英文标题】:Declare a delegate type in Typescript 【发布时间】:2013-12-17 02:28:10 【问题描述】:

来自 C# 背景,我想创建一个定义函数签名的数据类型。在 C# 中,这是一个 delegate 声明如下:

delegate void Greeter (string message);

public class Foo

    public void SayHi (Greeter g) 
        g("Hi!");
    

现在,我想在 Typescript 中实现类似的功能。我知道 Typescript 没有委托类型,而只有 lambdas。我想出了这样的事情:

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

虽然这可行,但我想多次重复使用方法签名(msg:String) => void,并认为创建自定义类型会更简洁——比如 C# 中的委托。

有什么想法可以做到这一点吗?

【问题讨论】:

Are strongly-typed functions as parameters possible in TypeScript?的可能重复 【参考方案1】:

您可以使用type alias 创建类似委托的东西:

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;
    

【讨论】:

仅供参考:这些称为类型别名【参考方案2】:

五年后,很多很多 TS 版本我发现自己使用更简单的 type 定义来声明函数类型:

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

【讨论】:

请注意,第 2 行的 : string 不是必需的;可以根据分配给Greeter 来推断类型。【参考方案3】:

我现在发布和使用@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");

【讨论】:

【参考方案4】:

可调用表达式的类型定义(这是一个草稿,对人类来说……不是 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);

【讨论】:

【参考方案5】:

在 TypeScript 中,接口可以有调用签名。在您的示例中,您可以这样声明:

interface Greeter 
    (message: string): void;


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


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

【讨论】:

不太一样,但我们拥有最好的。我只是讨厌在匿名强类型函数应该做的时候必须到处声明接口。 不确定你的意思——你也可以有匿名函数类型。 我想声明一个接收回调委托的函数,例如。 C# 中的 Func,如何在 TypeScript 中声明?使用 lambda 运算符用于声明委托的实例而不是类型。类型是匿名委托 Func。等效语法是什么? 例如function foo(x: (n: number) =&gt; string) console.log(x(3)); ,或等效的function foo(x: (n: number): string; ) ... 如何声明和导出作为 Greeter 实例的函数,以便在将欢迎函数导入不同文件时获得正确的智能感知?

以上是关于在 Typescript 中声明一个委托类型的主要内容,如果未能解决你的问题,请参考以下文章

如何在打字稿中正确导入自定义类型

163-委托的定义和声明

有没有办法将类型声明中特定键的值用作同一声明中另一个键的类型(在 Typescript 中)?

在 TypeScript 中使用导入类型的环境声明

TypeScript初认识

C#委托初学