游戏开发的TypeScript(3)匿名函数的常见和不常见用法
在 TypeScript 中,匿名函数是一种强大的工具,它继承了 JavaScript 的灵活性,并且通过类型系统增强了安全性和表达力。游戏开发,尤其是结构性框架的开发中经常使用这些特性。
一、基础语法与类型注解
1. 函数表达式
// 显式类型注解
const add: (a: number, b: number) => number = function(a, b) {return a + b;
};// 类型推断(推荐)
const subtract = (a: number, b: number): number => a - b;
2. 参数类型与可选参数
// 可选参数(? 标记)
const greet = (name: string, age?: number): string => {return age ? `${name}, ${age}岁` : name;
};// 默认值
const calculate = (a: number, b: number = 10): number => a + b;
二、高级参数类型
1. 省略参数(Rest Parameters)
const sum = (...numbers: number[]): number => {return numbers.reduce((acc, num) => acc + num, 0);
};sum(1, 2, 3); // 6
2. 元组参数(Tuple Parameters)
const printPoint = ([x, y]: [number, number]): void => {console.log(`Point: (${x}, ${y})`);
};printPoint([3, 4]); // 正确
printPoint([3, 4, 5]); // 错误:元组长度不匹配
3. 泛型参数(Generic Parameters)
// 泛型函数:返回传入的值本身
const identity = <T>(value: T): T => value;const str = identity<string>("hello"); // str 类型为 string
const num = identity(123); // 类型推断:num 类型为 number
三、函数重载(Function Overloading)
TypeScript 允许定义多个函数签名,增强类型安全。
// 重载签名
function formatDate(date: string): Date;
function formatDate(date: number): Date;// 实现签名(需兼容所有重载)
function formatDate(date: string | number): Date {return typeof date === "string" ? new Date(date) : new Date(date * 1000);
}formatDate("2023-01-01"); // 正确
formatDate(1672531200); // 正确
formatDate(true); // 错误:不匹配任何重载
四、上下文类型与 this 参数
1. 箭头函数的上下文继承
interface User {name: string;greet: () => void;
}const user: User = {name: "Alice",greet: function() {setTimeout(() => {console.log(this.name); // 箭头函数继承 this 类型}, 1000);}
};
2. 显式 this 参数(高级场景)
interface DBService {query(this: DBService, sql: string): void;
}function createQuery(this: DBService, sql: string) {return () => this.query(sql); // 确保 this 类型安全
}
五、条件类型与函数重载结合
// 根据参数类型返回不同类型
type ReturnType<T> = T extends string ? number : string;function process<T extends string | number>(value: T): ReturnType<T> {return (typeof value === "string" ? value.length : value.toString()) as ReturnType<T>;
}const strLength = process("hello"); // strLength 类型为 number
const numStr = process(123); // numStr 类型为 string
六、泛型约束与映射类型
1. 泛型约束
function getProperty<T, K extends keyof T>(obj: T, key: K) {return obj[key];
}const user = { name: "Alice", age: 30 };
getProperty(user, "name"); // 正确
getProperty(user, "invalid"); // 错误:invalid 不是 user 的属性
2. 映射类型与函数
type ReadonlyProps<T> = {readonly [K in keyof T]: T[K];
};function freeze<T>(obj: T): ReadonlyProps<T> {return Object.freeze(obj);
}const frozenUser = freeze({ name: "Bob" });
frozenUser.name = "Charlie"; // 错误:无法修改只读属性
七、函数类型别名与接口
1. 函数类型别名
type BinaryOperation = (a: number, b: number) => number;const add: BinaryOperation = (a, b) => a + b;
const multiply: BinaryOperation = (a, b) => a * b;
2. 接口定义函数
interface Comparator<T> {(a: T, b: T): number;
}const stringSorter: Comparator<string> = (a, b) => a.localeCompare(b);
八、回调函数与高阶函数
1. 回调函数类型
function fetchData(callback: (data: string) => void) {// 模拟异步操作setTimeout(() => callback("Data loaded"), 1000);
}fetchData((data) => {console.log(data.toUpperCase()); // data 类型自动推断为 string
});
2. 高阶函数
function withLogging<T extends (...args: any[]) => any>(fn: T): T {return ((...args: Parameters<T>) => {console.log(`Calling ${fn.name} with ${args}`);const result = fn(...args);console.log(`Result: ${result}`);return result;}) as T;
}const add = (a: number, b: number) => a + b;
const loggedAdd = withLogging(add);
loggedAdd(3, 4); // 输出日志并返回 7
九、类型守卫与函数重载
// 类型守卫函数
function isNumber(value: any): value is number {return typeof value === "number";
}// 重载签名
function parseValue(value: string): number;
function parseValue(value: number): number;
function parseValue(value: string | number): number {return isNumber(value) ? value : parseInt(value);
}
十、实用技巧
1. 可选链与空值合并
type User = {name: string;address?: {street?: string;};
};const getUserStreet = (user: User) => user?.address?.street ?? "Unknown";
2. 函数组合
const compose = <T, U, V>(f: (x: T) => U, g: (y: U) => V) => (x: T): V => g(f(x));const double = (x: number) => x * 2;
const square = (x: number) => x ** 2;const doubleThenSquare = compose(double, square);
doubleThenSquare(3); // (3*2)² = 36
总结
TypeScript 的匿名函数通过以下特性增强了 JavaScript:
类型安全:参数和返回值类型检查
泛型:处理多种类型的灵活性
函数重载:支持多种调用签名
高级类型:条件类型、映射类型等与函数结合
上下文类型:精确控制 this
和回调函数类型
有些特性如果不了解规则看起来容易云里雾里,所以一般在游戏开发中逻辑代码中不会使用,但是在框架封装中使用,可以使执行更加高效。