跳过正文
Background Image

TypeScript 最佳实践:提升代码质量的实用技巧

·574 字·3 分钟· loading · loading · ·

🎯 TypeScript 核心优势
#

TypeScript 作为 JavaScript 的超集,通过静态类型检查帮助我们在开发阶段发现潜在问题,提升代码质量和开发体验。

✨ 主要特性
#

  • 静态类型检查: 编译时发现类型错误
  • 智能提示: IDE 提供准确的代码补全
  • 重构安全: 类型安全的重构操作
  • 文档化: 类型即文档,提高代码可读性

🏗️ 类型定义最佳实践
#

1. 接口 vs 类型别名
#

// 推荐:使用接口定义对象结构
interface User {
  id: number;
  name: string;
  email: string;
  isActive?: boolean; // 可选属性
}

// 推荐:使用类型别名定义联合类型或复杂类型
type Status = 'pending' | 'approved' | 'rejected';
type UserWithRole = User & { role: 'admin' | 'user' };

2. 泛型的使用
#

// 通用函数
function identity<T>(arg: T): T {
  return arg;
}

// 泛型接口
interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

// 泛型约束
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

🔒 类型安全技巧
#

1. 严格模式配置
#

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true
  }
}

2. 类型守卫
#

// 类型谓词
function isString(value: unknown): value is string {
  return typeof value === 'string';
}

// 使用类型守卫
function processValue(value: unknown) {
  if (isString(value)) {
    // TypeScript 知道 value 是 string 类型
    console.log(value.toUpperCase());
  }
}

🎨 代码组织
#

1. 模块化设计
#

// user.types.ts
export interface User {
  id: number;
  name: string;
}

// user.service.ts
import { User } from './user.types';

export class UserService {
  async getUser(id: number): Promise<User> {
    // 实现逻辑
  }
}

2. 命名空间 vs 模块
#

// 推荐:使用模块
// math.ts
export function add(a: number, b: number): number {
  return a + b;
}

// 避免:命名空间
namespace Math {
  export function add(a: number, b: number): number {
    return a + b;
  }
}

🚀 性能优化
#

1. 类型推断
#

// 让 TypeScript 自动推断类型
const numbers = [1, 2, 3, 4, 5]; // 类型: number[]
const user = { name: 'John', age: 30 }; // 类型: { name: string; age: number }

// 避免过度类型注解
// 不推荐
const name: string = 'John';
// 推荐
const name = 'John';

2. 条件类型
#

type NonNullable<T> = T extends null | undefined ? never : T;
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

🔧 实用工具类型
#

1. 内置工具类型
#

// 部分属性可选
type PartialUser = Partial<User>;

// 所有属性只读
type ReadonlyUser = Readonly<User>;

// 选择特定属性
type UserName = Pick<User, 'name' | 'email'>;

// 排除特定属性
type UserWithoutId = Omit<User, 'id'>;

2. 自定义工具类型
#

// 深度部分可选
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

// 递归只读
type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};

📝 错误处理
#

1. Result 类型模式
#

type Result<T, E = Error> = 
  | { success: true; data: T }
  | { success: false; error: E };

async function fetchUser(id: number): Promise<Result<User>> {
  try {
    const user = await api.getUser(id);
    return { success: true, data: user };
  } catch (error) {
    return { success: false, error: error as Error };
  }
}

2. 异常类型
#

class ValidationError extends Error {
  constructor(
    message: string,
    public field: string,
    public value: unknown
  ) {
    super(message);
    this.name = 'ValidationError';
  }
}

🧪 测试策略
#

1. 类型测试
#

// 确保类型正确
type Assert<T extends true> = T;
type IsString<T> = T extends string ? true : false;

// 类型测试
type Test1 = Assert<IsString<'hello'>>; // true
type Test2 = Assert<IsString<123>>; // 编译错误

2. 测试工具
#

// 使用 tsd 进行类型测试
import { expectType } from 'tsd';

expectType<string>('hello');
expectType<number>(123);

💡 最佳实践总结
#

  1. 启用严格模式: 充分利用 TypeScript 的类型检查
  2. 优先使用接口: 定义对象结构时使用接口
  3. 合理使用泛型: 提高代码复用性和类型安全性
  4. 避免 any 类型: 尽可能使用具体类型
  5. 利用类型推断: 让 TypeScript 自动推断类型
  6. 使用工具类型: 减少重复的类型定义
  7. 模块化设计: 使用 ES6 模块而不是命名空间

📚 学习资源
#


掌握这些最佳实践,让你的 TypeScript 代码更加健壮和易维护!