来自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#中的委托一样。
任何想法如何做到这一点?
答案 0 :(得分:60)
在TypeScript中,接口可以有呼叫签名。在您的示例中,您可以这样声明:
interface Greeter {
(message: string): void;
}
function sayHi(greeter: Greeter) {
greeter('Hello!');
}
sayHi((msg) => console.log(msg)); // msg is inferred as string
答案 1 :(得分:24)
您可以创建像这样的委托:
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 :(得分: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);
答案 3 :(得分:1)
五年后,许多TS版本后来发现我使用了一个更简单的type
定义来声明函数类型:
type Greeter = (msg: string) => void;
const someGreeter: Greeter = (msg: string) => `Hi there with ${msg}`;
答案 4 :(得分: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");