TypeScript 高级特性
TypeScript 提供了许多高级类型和特性,掌握这些可以帮助我们写出更加健壮和类型安全的代码。
高级类型
1. 交叉类型(Intersection Types)
使用 & 运算符将多个类型合并为一个类型:
interface BusinessPartner {
name: string;
credit: number;
}
interface Identity {
id: number;
email: string;
}
type Employee = BusinessPartner & Identity;
// 使用示例
let emp: Employee = {
name: "John",
credit: 100,
id: 1234,
email: "john@example.com"
};
2. 联合类型(Union Types)
使用 | 运算符表示一个值可以是几种类型之一:
type StringOrNumber = string | number;
type Status = "success" | "error" | "pending";
function printId(id: number | string) {
if (typeof id === "string") {
console.log(id.toUpperCase());
} else {
console.log(id);
}
}
3. 类型守卫(Type Guards)
帮助TypeScript推断类型的表达式:
// typeof 类型守卫
function padLeft(value: string, padding: string | number) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error("Expected string or number");
}
// instanceof 类型守卫
class Bird {
fly() {
console.log("flying...");
}
}
class Fish {
swim() {
console.log("swimming...");
}
}
function move(pet: Bird | Fish) {
if (pet instanceof Bird) {
pet.fly();
} else {
pet.swim();
}
}
4. 映射类型(Mapped Types)
从现有类型创建新类型:
// Readonly
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
// Partial
type Partial<T> = {
[P in keyof T]?: T[P];
};
// Pick
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
// Record
type Record<K extends keyof any, T> = {
[P in K]: T;
};
5. 条件类型(Conditional Types)
根据条件选择类型:
type NonNullable<T> = T extends null | undefined ? never : T;
// 示例
type EmailAddress = string | null | undefined;
type NonNullableEmail = NonNullable<EmailAddress>; // string
// 条件类型与泛型结合
type ArrayType<T> = T extends any[] ? T[number] : T;
type StringArray = ArrayType<string[]>; // string
type NumberValue = ArrayType<number>; // number
高级特性
1. 装饰器(Decorators)
用于修改类的行为:
function logged(constructor: Function) {
console.log(`Creating new instance of ${constructor.name}`);
}
@logged
class Person {
constructor(public name: string) {}
}
// 方法装饰器
function measure(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
const start = performance.now();
const result = originalMethod.apply(this, args);
const finish = performance.now();
console.log(`${propertyKey} took ${finish - start}ms`);
return result;
};
}
2. 高级类型推断
// ReturnType
function f() {
return { x: 10, y: 3 };
}
type P = ReturnType<typeof f>; // { x: number, y: number }
// Parameters
type T0 = Parameters<() => string>; // []
type T1 = Parameters<(s: string) => void>; // [string]
// InstanceType
class C {
x = 0;
y = 0;
}
type T2 = InstanceType<typeof C>; // C
3. 模块增强(Module Augmentation)
扩展现有模块的类型定义:
// 原始模块
declare module "myModule" {
export interface BaseOptions {
timeout: number;
}
}
// 增强模块
declare module "myModule" {
interface BaseOptions {
retries?: number;
}
}
最佳实践
1. 类型安全
// 使用严格的类型检查
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true
}
}
// 避免使用 any
function processData<T>(data: T): T {
// 处理数据
return data;
}
2. 类型断言最佳实践
// 使用 as const 断言
const config = {
endpoint: "api.example.com",
port: 443
} as const;
// 双重断言(谨慎使用)
let someValue: unknown = "this is a string";
let strLength: number = (someValue as string).length;
3. 泛型约束最佳实践
interface HasLength {
length: number;
}
// 泛型约束确保参数有length属性
function logLength<T extends HasLength>(arg: T): number {
return arg.length;
}
// 可以传入字符串或数组
logLength("Hello"); // OK
logLength([1, 2, 3]); // OK
logLength(123); // Error: number doesn't have length