TypeScript 高级类型
TypeScript 的类型系统是其最强大的特性之一,提供了静态类型检查、接口、泛型、装饰器等高级功能。掌握这些高级类型技巧可以显著提升代码质量和开发效率。
泛型(Generics)
泛型允许我们创建可重用的组件,这些组件可以支持多种类型而不失去类型安全性。
// 基本泛型函数
function identity(arg: T): T {
return arg;
}
// 使用
let output1 = identity("hello");
let output2 = identity(42);
let output3 = identity("TypeScript"); // 类型推断
// 泛型接口
interface GenericIdentityFn {
(arg: T): T;
}
// 泛型类
class GenericNumber {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = (x, y) => x + y;
条件类型(Conditional Types)
条件类型允许我们根据类型关系选择不同的类型,这是TypeScript类型系统的高级功能。
// 条件类型示例
type IsString = T extends string ? true : false;
type A = IsString; // true
type B = IsString; // false
// 条件类型与infer关键字
type ReturnType = T extends (...args: any[]) => infer R ? R : any;
function getUser() {
return { name: "John", age: 30 };
}
type User = ReturnType; // { name: string; age: number }
映射类型(Mapped Types)
映射类型允许我们基于旧类型创建新类型,这在处理对象类型时特别有用。
// 只读映射类型
type Readonly = {
readonly [P in keyof T]: T[P];
};
// 可选映射类型
type Partial = {
[P in keyof T]?: T[P];
};
// 实际应用
interface User {
id: number;
name: string;
email: string;
}
type ReadonlyUser = Readonly;
// 等同于:
// {
// readonly id: number;
// readonly name: string;
// readonly email: string;
// }
type PartialUser = Partial;
// 等同于:
// {
// id?: number;
// name?: string;
// email?: string;
// }
// 实用工具类型
type Pick = {
[P in K]: T[P];
};
type Omit = Pick>;
// 使用示例
type UserBasicInfo = Pick;
type UserWithoutEmail = Omit;
装饰器(Decorators)
装饰器是一种特殊类型的声明,可以附加到类声明、方法、访问器、属性或参数上,用于修改类的行为。
// 类装饰器
function LogClass(target: Function) {
console.log(`类 ${target.name} 被装饰`);
}
function AddTimestamp(constructor: Function) {
constructor.prototype.createdAt = new Date();
}
// 方法装饰器
function LogMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`调用方法: ${propertyKey}`);
console.log(`参数: ${JSON.stringify(args)}`);
const result = originalMethod.apply(this, args);
console.log(`返回值: ${result}`);
return result;
};
return descriptor;
}
// 属性装饰器
function DefaultValue(value: any) {
return function(target: any, propertyKey: string) {
Object.defineProperty(target, propertyKey, {
get: function() {
return this[`_${propertyKey}`] || value;
},
set: function(newValue) {
this[`_${propertyKey}`] = newValue;
},
enumerable: true,
configurable: true
});
};
}
// 使用装饰器
@LogClass
@AddTimestamp
class UserService {
@DefaultValue("default user")
username: string;
constructor(username?: string) {
if (username) this.username = username;
}
@LogMethod
greet(message: string): string {
return `${message}, ${this.username}!`;
}
}
类型体操实用技巧
1. 类型守卫(Type Guards)
// 自定义类型守卫
function isString(value: any): value is string {
return typeof value === "string";
}
function processValue(value: string | number) {
if (isString(value)) {
// 这里value被推断为string类型
console.log(value.toUpperCase());
} else {
// 这里value被推断为number类型
console.log(value.toFixed(2));
}
}
2. 索引签名(Index Signatures)
interface StringDictionary {
[key: string]: string;
}
interface NumberOrStringDictionary {
[key: string]: number | string;
length: number; // 必须与索引签名兼容
name: string;
}
3. 模板字面量类型(Template Literal Types)
// TypeScript 4.1+
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type ApiEndpoint = `/api/${string}`;
type FullApiPath = `${HttpMethod} ${ApiEndpoint}`;
type EventName = "click" | "change" | "input";
type HandlerName = `on${Capitalize}`;
// 结果为: "onClick" | "onChange" | "onInput"
TypeScript的高级类型系统为大型项目提供了强大的类型安全保障。通过掌握这些高级技巧,您可以编写出更健壮、更易维护的代码,并充分利用TypeScript的类型检查能力。