Appearance
TypeScript 函数类型
函数是 TypeScript 中的重要组成部分,本章节将介绍如何为函数添加类型注解,包括参数类型、返回值类型、可选参数、默认参数、剩余参数、函数重载等。
函数参数类型
为函数参数添加类型注解:
示例:
typescript
// 为参数添加类型注解
function add(a: number, b: number): number {
return a + b;
}
function greet(name: string): string {
return `Hello, ${name}!`;
}
// 调用函数
const sum = add(1, 2); // 3
const message = greet("John"); // Hello, John!
// 错误:参数类型不匹配
// add("1", 2); // 错误:Argument of type 'string' is not assignable to parameter of type 'number'函数返回值类型
为函数返回值添加类型注解:
示例:
typescript
// 为返回值添加类型注解
function add(a: number, b: number): number {
return a + b; // 正确:返回 number 类型
}
function greet(name: string): string {
return `Hello, ${name}!`; // 正确:返回 string 类型
}
function isEven(num: number): boolean {
return num % 2 === 0; // 正确:返回 boolean 类型
}
// 无返回值函数
function logMessage(message: string): void {
console.log(message); // 正确:无返回值
}
// 错误:返回值类型不匹配
// function getNumber(): number {
// return "42"; // 错误:Type 'string' is not assignable to type 'number'
// }可选参数
使用 ? 符号标记可选参数:
示例:
typescript
// 可选参数
function greet(name: string, greeting?: string): string {
if (greeting) {
return `${greeting}, ${name}!`;
}
return `Hello, ${name}!`;
}
// 调用函数
console.log(greet("John")); // Hello, John!
console.log(greet("John", "Hi")); // Hi, John!
// 可选参数必须放在必选参数之后
// function greetOptional(greeting?: string, name: string): string { // 错误:必选参数不能位于可选参数之后
// return `${greeting || "Hello"}, ${name}!`;
// }默认参数
为参数设置默认值:
示例:
typescript
// 默认参数
function calculateTotal(price: number, tax: number = 0.08): number {
return price + price * tax;
}
// 调用函数
console.log(calculateTotal(100)); // 108
console.log(calculateTotal(100, 0.1)); // 110
// 默认参数可以是表达式
function getDate(date: Date = new Date()): string {
return date.toISOString();
}
console.log(getDate()); // 当前日期
console.log(getDate(new Date(2024, 0, 1))); // 2024-01-01T00:00:00.000Z剩余参数
使用 ... 语法定义剩余参数:
示例:
typescript
// 剩余参数
function sum(...numbers: number[]): number {
return numbers.reduce((acc, curr) => acc + curr, 0);
}
// 调用函数
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15
// 混合使用普通参数和剩余参数
function concatenate(separator: string, ...strings: string[]): string {
return strings.join(separator);
}
console.log(concatenate(", ", "a", "b", "c")); // a, b, c函数重载
函数重载允许你为同一个函数定义多个签名:
示例:
typescript
// 函数重载签名
function process(value: string): string;
function process(value: number): number;
function process(value: boolean): boolean;
// 函数实现
function process(value: string | number | boolean): string | number | boolean {
if (typeof value === "string") {
return value.toUpperCase();
} else if (typeof value === "number") {
return value * 2;
} else {
return !value;
}
}
// 调用函数
console.log(process("hello")); // HELLO
console.log(process(42)); // 84
console.log(process(true)); // false
// 错误:没有匹配的重载签名
// process(null); // 错误:No overload matches this call箭头函数类型
为箭头函数添加类型注解:
示例:
typescript
// 箭头函数类型注解
const add = (a: number, b: number): number => {
return a + b;
};
const greet = (name: string): string => `Hello, ${name}!`;
const isEven = (num: number): boolean => num % 2 === 0;
// 调用函数
console.log(add(1, 2)); // 3
console.log(greet("John")); // Hello, John!
console.log(isEven(4)); // true
// 箭头函数类型别名
type AddFunction = (a: number, b: number) => number;
const addNumbers: AddFunction = (a, b) => a + b;
console.log(addNumbers(5, 10)); // 15实战:给工具函数加类型
示例 1:数组工具函数
typescript
// 数组工具函数
// 过滤数组
function filter<T>(array: T[], predicate: (item: T) => boolean): T[] {
return array.filter(predicate);
}
// 映射数组
function map<T, U>(array: T[], mapper: (item: T) => U): U[] {
return array.map(mapper);
}
// 查找元素
function find<T>(array: T[], predicate: (item: T) => boolean): T | undefined {
return array.find(predicate);
}
// 使用
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = filter(numbers, (num) => num % 2 === 0);
console.log(evenNumbers); // [2, 4]
const doubled = map(numbers, (num) => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
const found = find(numbers, (num) => num > 3);
console.log(found); // 4
// 字符串数组
const strings = ["a", "b", "c", "d"];
const longStrings = filter(strings, (str) => str.length > 1);
console.log(longStrings); // []
const uppercased = map(strings, (str) => str.toUpperCase());
console.log(uppercased); // ["A", "B", "C", "D"]示例 2:对象工具函数
typescript
// 对象工具函数
// 深拷贝对象
function deepClone<T>(obj: T): T {
if (obj === null || typeof obj !== "object") {
return obj;
}
if (obj instanceof Date) {
return new Date(obj.getTime()) as T;
}
if (obj instanceof Array) {
return obj.map((item) => deepClone(item)) as T;
}
const clonedObj = {} as T;
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clonedObj[key] = deepClone(obj[key]);
}
}
return clonedObj;
}
// 合并对象
function merge<T extends object, U extends object>(obj1: T, obj2: U): T & U {
return { ...obj1, ...obj2 };
}
// 使用
const person = {
name: "John",
age: 30
};
const address = {
street: "123 Main St",
city: "New York"
};
const merged = merge(person, address);
console.log(merged); // { name: "John", age: 30, street: "123 Main St", city: "New York" }
const original = {
name: "John",
address: {
street: "123 Main St",
city: "New York"
}
};
const cloned = deepClone(original);
original.address.city = "Boston";
console.log(cloned.address.city); // New York (深拷贝,不受影响)小结
本章节介绍了 TypeScript 函数类型的使用,包括:
- 函数参数类型
- 函数返回值类型
- 可选参数
- 默认参数
- 剩余参数
- 函数重载
- 箭头函数类型
- 实战:给工具函数加类型
为函数添加类型注解可以提高代码的类型安全性和可维护性,特别是在大型项目中。通过为函数参数和返回值添加类型注解,你可以在编译时捕获类型错误,避免在运行时出现问题。
在实际开发中,应该为所有函数添加适当的类型注解,特别是公共 API 和工具函数,以提高代码的可读性和可维护性。
