Coming from a C# background, I want to create a datatype that defines a function signature. In C#, this is a delegate
declared like this:
delegate v
You can create something like a delegate by using a type alias:
type MyDelegate = (input: string) => void;
which defines a type name for a function pointer, just as delegates do in C#. The following example uses it in combination with generic type parameters:
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;
}
}
Five years and many, many TS versions later I find myself using a simpler type
definition for declaring function types:
type Greeter = (msg: string) => void;
const someGreeter: Greeter = (msg: string) => `Hi there with ${msg}`;
Type definition for a callable expression (this is a draft ok, for humans... not a BNF or anything formal):
callableType: (paramsDef) => returnType
paramsDef: MULTIPLE paramDef SEPARATED BY ,
paramDef: EITHER paramName: paramType
OR optionalParamName?: paramTypeWhenDefined
OR ...manyParamName: eachParamType[]
Example:
var func = something as ((...x: any[]) => any);
Then you can:
var result = func("a", "b", 2);
In TypeScript, interfaces can have call signatures. In your example, you could declare it like this:
interface Greeter {
(message: string): void;
}
function sayHi(greeter: Greeter) {
greeter('Hello!');
}
sayHi((msg) => console.log(msg)); // msg is inferred as string
I now publish and use @steelbreeze/delegate; it has a few limitations compared to the C# delegate, in that it's immutable, but otherwise works well (and when called returns results from all the functions called).
It lets you write code such as:
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");