TypeScript-Function

More on Functions

Function Type Expressions

The simplest way to describe a function is with a function type expression.

1
2
3
4
5
6
7
8
9
10
function greeter(fn: (a: string) => void) {
fn("Hello, Word");
}

function printToConsole(s: string) {
console.log(s);
}

greeter(printToConsole);

we can use a type alias to name a function type:

1
2
3
4
5
type GreetFunction = (a: string) => void;

function greeter(fn: GreetFGunction) {
// ...
}

Call Signatures 调用签名

if we want to describe something callable with properties, we can write a call signature in an object type:

1
2
3
4
5
6
7
8
type DescribableFunction = {
description: string;
(someArg: number): boolean;
};

function doSomething(fn: DescribableFunction) {
console.log(fn.description + "returned" + fn(6));
}

Construct Signatures

You can write a construct signature by adding the new keyword in front of a call signature.

1
2
3
4
5
6
7
8
type SomeConstructor = {
new (s: string): SomeObject;
}

function fn(ctor: SomeConstructor) {
return new ctor("hello");
}

Some objects, like JavaScript’s Date object, can be called with or without new You can combine call and construct signatrues in the same type arbitarily.

1
2
3
4
interface CallOrConstruct {
new (s: string): Date;
(n?: number): number;
}

Generic Functions 通用函数

In TypeScript, generics are used when we want to describe a correspondence between two values. We do this by declaring a type parameter in function signature.

1
2
3
4
5
6
7
8
9
10
11
function firstElement<Type>(arr: Type[]): Type | undefined {
return arr[0];
}

function map<Input, Output>(arr: Input[], func: (arg: Input) => Output) {
return arr.map(func);
}
// Parameter 'n' is of type 'string'
// 'parsed' is of type 'number[]'
const parsed = map(["1", "2", "3"], (n) => parseInt(n));

When we need a length property that’s a number. We constrain the type parameter to that type by writing an extends clause:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function longest<Type extends { length: number }>(a: Type, b: Type) {
if (a.length >= b.length) {
return a;
} else {
return b;
}
}

function filter1<Type>(arr: Type[], func: (arg: Type) => boolean): Type[] {
return arr.filter(func);
}

function filter2<Type, Func extends (arg: Type) => boolean>(arr: Type[], func: Func): Type[] {
return arr.filter(func);
}

Optional Parameters in Callbacks

1
2
3
4
5
6
7
8
function myForEach(arr:any[], callback: (arg: any, index?: number) => void) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i], i);
}
}

myForEach([1, 2, 3], (a) => console.log(a));
myForEach([1, 2, 3], (a, i) => console.log(a, i));