【问题标题】:Declare a delegate type in Typescript在 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# 中的委托。

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

【问题讨论】:

标签: c# types lambda delegates 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 实例的函数,以便在将欢迎函数导入不同文件时获得正确的智能感知?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-01
      • 1970-01-01
      • 2017-08-30
      • 1970-01-01
      • 2021-01-03
      相关资源
      最近更新 更多