More on Functions
Function Type Expressions
函数类型表达式, 语法:(a: string) => void
ts
function greeter(fn: (a: string) => void) {
fn('Hello, World');
}
function printToConsole(s: string) {
console.log(s);
}
greeter(printToConsole);
给一个函数类型起一个类型别名
ts
type GreetFunction = (a: string) => void;
function greeter(fn: GreetFunction) {
// ...
}
Call Signatures
函数调用签名
ts
type DescribableFunction = {
description: string;
(someArg: number): boolean;
};
function doSomething(fn: DescribableFunction) {
console.log(fn.description + ' returned ' + fn(6));
}
function myFunc(someArg: number) {
return someArg > 3;
}
// key: myFunc 变成 DescribableFunction 类型
myFunc.description = 'default description';
doSomething(myFunc);
Construct Signatures
构造函数签名
ts
type SomeConstructor = {
new (s: string): SomeObject;
};
function fn(ctor: SomeConstructor) {
return new ctor('hello');
}
Generic Functions
泛型函数
ts
// normal function
function firstElement(arr: any[]) {
return arr[0];
}
// Generic Functions
function firstElement<Type>(arr: Type[]): Type | undefined {
return arr[0];
}
const s = firstElement(['a', 'b', 'c']); // string
const n = firstElement([1, 2, 3]); // number
const u = firstElement([]); // undefined
Inference
自动类型推导
ts
function map<Input, Output>(arr: Input[], func: (arg: Input) => Output): Output[] {
return arr.map(func);
}
// Input: string
// Output: number
const parsed = map(['1', '2', '3'], (n) => parseInt(n));
Constraints
约束: extends
关键字
ts
function longest<Type extends { length: number }>(a: Type, b: Type) {
if (a.length >= b.length) {
return a;
} else {
return b;
}
}
const longerArray = longest([1, 2], [1, 2, 3]); // Ok
const longerString = longest('alice', 'bob'); // Ok
const notOK = longest(10, 100); // Error: number类型没有 length 成员属性
Specifying Type Arguments
ts
function combine<Type>(arr1: Type[], arr2: Type[]): Type[] {
return arr1.concat(arr2);
}
// Error: 识别到第一个参数时,自动推导 Type 为number;第二个参数string数组就会报错
const arr = combine([1, 2, 3], ['hello']);
// Ok: 调用时指定类型
const arr = combine<string | number>([1, 2, 3], ['hello']);
Guidelines for Writing Good Generic Functions
Push Type Parameters Down
ts
function firstElement1<Type>(arr: Type[]) {
return arr[0];
}
// 抽象
function firstElement2<Type extends any[]>(arr: Type) {
return arr[0];
}
// a: number (good)
const a = firstElement1([1, 2, 3]);
// b: any (bad)
const b = firstElement2([1, 2, 3]);
Use Fewer Type Parameters
ts
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);
}
Type Parameters Should Appear Twice
ts
function greet<Str extends string>(s: Str) {
console.log('Hello, ' + s);
}
greet('world');
// 只使用一次,可以写成更简单的方式
function greet(s: string) {
console.log('Hello, ' + s);
}
Optional Parameters
可选参数:
ts
// 使用`?`问号表示可选参数
function f(x?: number) {
// ...
}
f(); // OK
f(10); // OK
f(undefined); // OK
// 给参数设置默认值
function f(x = 10) {
// ...
}
Optional Parameters in Callbacks
回调中的可选参数
ts
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));
Function Overloads
ts
// 两个是重载函数
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
// 函数实现:
// - 参数要兼容选项函数
// - 返回值得一样
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
} else {
return new Date(mOrTimestamp);
}
}
const d1 = makeDate(12345678);
const d2 = makeDate(5, 5, 5);
const d3 = makeDate(1, 3); // Error: 必须使用重载函数中的一种
Other Types to Know About
- void
- object
- unknown
- never
- Function
void
void描述函数不返回值
never
用在函数返回值,表示函数永远不会返回
ts
function fail(msg: string): never {
throw new Error(msg);
}
ts
// The inferred return type is void
function noop() {
return;
}
Rest Parameters and Arguments
Rest Parameters
剩余参数
ts
function multiply(n: number, ...m: number[]) {
return m.map((x) => n * x);
}
// 'a' gets value [10, 20, 30, 40]
const a = multiply(10, 1, 2, 3, 4);
Rest Arguments
剩余传数
ts
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
arr1.push(...arr2);
Parameter Destructuring
参数解构
ts
function sum({ a, b, c }: { a: number; b: number; c: number }) {
console.log(a + b + c);
}
// 同上
type ABC = { a: number; b: number; c: number };
function sum({ a, b, c }: ABC) {
console.log(a + b + c);
}