0%

Learning TypeScript From Scratch(3)

Functions


Representations

1
2
3
4
5
function func(x: number, y: number): number { ... }

let func = function (x: number, y: number): number { ... }

let func: (x: number, y: number) => number = ...

Optional/Default/Rest parameters

By default, the number of arguments given to a function has to match the number of parameters the function expects. That’s to say, parameters can’t be too few or too many, or we will get an error.

1
2
3
4
5
6
7
8
// Optional param
function func(x: number, y?: number) { ... }

// Default param
function func(x: number, y = 0) { ... }

// Rest param
function func(x: number, ...restParams: number[]) { ... }

This

There exist many problems using this in JavaScript. Arrow function could help, but it’s even better with TypeScript’s this parameter.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// this will be set to window instead of obj
let obj = {
val: 1,
returnFunc: function () {
return function () {
return { value: this.val };
};
}
}
let outerFunc = obj.returnFunc();
let outerobj = outerFunc(); // Problem: return { value: undefined }


// Fixed by arrow function
let obj = {
val: 1,
returnFunc: function () {
return () => {
// Problem: this.val is of type any
// and compiler would warn when --noImplicitThis flag is set
return { value: this.val };
}
}
}


// Fixed by this declaration
interface Ret {
value: number;
}

interface Obj {
val: number;
returnFunc(this: Obj): () => Ret
}

let obj = {
val: 1,
// now TypeScript knows returnFunc expects to be called on an Obj object
// and this.val should be of type number
returnFunc: function (this: Obj) {
return () => {
return { value: this.val };
}
}
}

Furthermore, by using this kind of method, we could prevent callback error with this. Sometimes we want a function not to using this, to make that constrain, we could pass this: void as parameter.

Example:

1
2
3
4
5
6
7
class Handler {
info: string;
onClickBad(this: void, e: event) {
// can't use `this` here because it's of type void!
this.info = e.message; // Error
}
}

Overloads

JavaScript is inherently a very dynamic language. It’s very common for a single JavaScript function to return different types of objects based on the shape of the arguments passed in. Typescript allow function to overload.

1
2
3
4
5
6
7
8
9
function func(x: string): boolean;
function func(x: number): string;
function func(param: any): any {
if (typeof param == "string") {
return true;
} else if (typeof param == "number") {
return "oops!";
}
}

Two things need to notice:

  • Order matters
    Underlying JavaScript keeps an overload list and finds the match one from head. So it’s customary to order overloads from most specific to least specific.
  • Return any is not included in the overload list
    Like above example has only two overloads: string => boolean、number => string. Calling func with any other parameter types would cause an error.