# Functions
TIP
TypeScript has many ways to describe how functions can be called. Let’s learn about how to write types that describe functions
# Basic
- TypeScript allows you to specify the types of both the
input
andoutput
values offunction
// with `string` parameter and return `number`
function greet(name: string): number {
console.log("Hello, " + name.toUpperCase() + "!!");
return 26;
}
fn: (a: string) => void
means with onestring
parameter, anddoesn’t
have areturn
value
function greeter(fn: (a: string) => void) {
fn("Hello, World");
}
function p(s: string) {
console.log(s);
}
greeter(p);
//------------
// type alias to name a function type
type GreetFunction = (a: string) => void;
function greeter(fn: GreetFunction) {
// ...
}
- NOTE: In JavaScript, functions can have properties in
addition
to being callable and invoked with thenew operator
. However, thefunction type expression
syntaxdoesn’t
allow fordeclaring
properties.
# Signatures
- If we want to describe something callable with properties, write a
call signature
in an object type
type d = {
description: string;
(someArg: number): boolean; // here is a call signature
};
function doSomething(fn: d) {
console.log(fn.description + " returned " + fn(6)); //see fu (...)
}
- You can write a
construct signature
by adding thenew
keyword in front of acall signature
type s = {
new (s: string): SomeObject;
};
function fn(ctor: s) {
return new ctor("hello"); // see new
}
# Generic Functions
- generics are used when we want to describe a
correspondence
betweentwo
values. - keyword :
constrained
function firstElement<Type>(arr: Type[]): Type | undefined {
return arr[0];
}
// s is of type 'string'
const s = firstElement(["a", "b", "c"]);
// n is of type 'number'
const n = firstElement([1, 2, 3]);
// u is of type undefined
const u = firstElement([]);
# Optional Parameters
- callers can always pass
undefined
, as this simply simulates a “missing” argument
function f(x?: number) {
// ...
}
f(); // OK
f(10); // OK
f(undefined); // ok
// set default
function f(x = 10) {
// ...
}
- When writing a
function type
for acallback
,never
write anoptional parameter
unless you intend to call the functionwithout
passing thatargument
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, i) => {
console.log(i.toFixed());
// i Object is possibly 'undefined'.
});
# Function Overloads
- In TypeScript, called in a
variety
of argument counts and types we can specify a function that can be called in different ways by writingoverload signatures
function fn(x: boolean): void; //signature1
function fn(x: string): void;//signature2
function fn(x: boolean) {}// error
function fn(x: boolean | string) {} //right, u must contain all param types
# 'this' in a Function
TypeScript
specification states (like js) that youcannot
have a parameter calledthis
, so just let youdeclare
thetype
forthis
in the functionbody
Note
that you need to usefunction
andnot
arrow functions to getthis
behavior
interface DB {
filterUsers(filter:
(this: User) => boolean // params : a function ;
): User[]; // return : array[]
}
const db = getDB();
const handler = function (this: User) {
return this.admin;
}
const admins = db.filterUsers(handler);
const admins = db.filterUsers(() => this.admin);// error
# Other Types
- these are especially
relevant
in thecontext
of functions
void
object
unknown
never
Function
void
represents the return value of functions whichdon’t
return a valuevoid
isnot
the same asundefined
function noop() { return; }
object
type refers to any value thatisn’t
a primitive (string, number, bigint, boolean, symbol, null, or undefined)object
is notObject
. Always useobject
!- This is different from the empty
object
type{ }
, and also different from theglobal
typeObject
unknown
type represents as a safer type ofany
value- it’s
not
legal to doanything
with anunknown
value
function f1(a: any) { a.b(); // OK } function f2(a: unknown) { a.b();// error: Object is of type 'unknown' }
- This is useful when describing
function
types
function safeParse(s: string): unknown { return JSON.parse(s); // we not really sure the return type }
- we should avoid use
any
for many cases, andunknown
only can assign tonuknown | any
declare let T: unknown; declare let v1: string; v1 = T; // error; declare let v2: number; v2 = T; // error; declare let v3: boolean; v3 = T; // error; declare let v4: number[]; v4 = T; // error; declare let v5: any; v5 = T; // ok; // any = unknown
- use
typeof
orinstanceof
to narrow the range ofunknown
makes your operations legally
if (typeof x === 'string') { ... } if (x instanceof Bird) { ... }
- it’s
- Some functions
never
return a value- function
throws
anexception
orterminates
execution of the program
function fail(msg: string): never { throw new Error(msg); }
- when
TypeScript
determines there’snothing
left in aunion
function fn(x: string | number) { if (typeof x === "string") { ... } else if (typeof x === "number") { ... } else { x; // has type 'never'! } }
- function
Function
describes properties likebind
,call
,apply
function doSomething(f: Function) {
f(1, 2, 3);
}
# Rest Parameters | Arguments
rest parameters
define functions that take anunbounded
number of arguments
function multiply(n: number, ...m: number[]) {// use the ... syntax
return m.map((x) => n * x);
}
const a = multiply(10, 1, 2, 3, 4); // [10, 20, 30, 40]
rest Arguments
const args = [8, 5];
const angle = Math.atan2(...args); // error
const args = [8, 5] as const;
const angle = Math.atan2(...args);// ok