TypeScript 精通指南

TypeScript 是 JavaScript 的超集,提供了强大的类型系统和现代编程特性。要精通 TypeScript,需要深入理解以下几个核心领域:

1. 类型系统深度掌握

基础类型

// 原始类型
let isDone: boolean = false;
let decimal: number = 6;
let color: string = "blue";

// 数组
let list: number[] = [1, 2, 3];
let genericList: Array<number> = [1, 2, 3];

// 元组
let tuple: [string, number] = ["hello", 10];

高级类型

// 联合类型
let id: string | number;

// 交叉类型
interface Named {
  name: string;
}
interface Aged {
  age: number;
}
type Person = Named & Aged;

// 类型别名
type StringOrNumber = string | number;
type Callback<T> = (data: T) => void;

// 条件类型
type IsString<T> = T extends string ? true : false;
type Result = IsString<"hello">; // true

// 映射类型
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};
type Optional<T> = {
  [P in keyof T]?: T[P];
};

2. 泛型深度应用

// 基础泛型
function identity<T>(arg: T): T {
  return arg;
}

// 泛型约束
interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

// 泛型类
class GenericNumber<T> {
  zeroValue: T;
  add: (x: T, y: T) => T;
}

// 泛型默认值
interface ApiResponse<T = any> {
  data: T;
  status: number;
}

// 泛型条件类型
type Flatten<T> = T extends Array<infer U> ? U : T;
type StringArray = Flatten<string[]>; // string

3. 高级类型技巧

类型推断

// infer 关键字
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
type Parameters<T> = T extends (...args: infer P) => any ? P : never;

// 模板字面量类型
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type ApiEndpoint = `/api/${string}`;
type FullEndpoint = `${HttpMethod} ${ApiEndpoint}`;

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

类型守卫和断言

// 用户定义类型守卫
function isString(value: any): value is string {
  return typeof value === 'string';
}

// 断言函数
function assert(condition: any, msg?: string): asserts condition {
  if (!condition) {
    throw new Error(msg);
  }
}

function assertIsNumber(value: any): asserts value is number {
  if (typeof value !== 'number') {
    throw new Error('Not a number');
  }
}

4. 装饰器(Decorators)

// 类装饰器
function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}

// 方法装饰器
function log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
  const method = descriptor.value;
  
  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyName} with`, args);
    return method.apply(this, args);
  };
}

// 属性装饰器
function format(formatString: string) {
  return function (target: any, propertyKey: string) {
    let value = target[propertyKey];
    
    const getter = () => value;
    const setter = (newVal: string) => {
      value = formatString.replace('{0}', newVal);
    };
    
    Object.defineProperty(target, propertyKey, {
      get: getter,
      set: setter
    });
  };
}

@sealed
class User {
  @format('Hello, {0}!')
  greeting: string;
  
  @log
  sayHello(name: string) {
    return `${this.greeting}, ${name}`;
  }
}

5. 命名空间和模块

// 命名空间
namespace Geometry {
  export interface Point {
    x: number;
    y: number;
  }
  
  export class Circle {
    constructor(public center: Point, public radius: number) {}
    
    area(): number {
      return Math.PI * this.radius ** 2;
    }
  }
}

// ES 模块
import { Circle, Point } from './geometry';

// 动态导入
async function loadModule() {
  const module = await import('./dynamic-module');
  module.doSomething();
}

6. 配置和工程化

tsconfig.json 深度配置

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "moduleResolution": "Node",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "removeComments": false,
    "noEmitOnError": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "incremental": true,
    "tsBuildInfoFile": "./dist/.tsbuildinfo"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

7. 性能优化和最佳实践

类型性能优化

// 避免过度使用 any
// 不好的做法
function processData(data: any): any {
  // ...
}

// 好的做法
function processData<T>(data: T): Processed<T> {
  // ...
}

// 使用 const 断言
const colors = ['red', 'green', 'blue'] as const;
type Color = typeof colors[number]; // "red" | "green" | "blue"

// 使用 satisfies 运算符(TS 4.9+)
const config = {
  width: 100,
  height: 200,
  color: 'red'
} satisfies Record<string, string | number>;

错误处理模式

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

function safeJsonParse(text: string): Result<any> {
  try {
    const data = JSON.parse(text);
    return { success: true, data };
  } catch (error) {
    return { success: false, error: error as Error };
  }
}

8. 测试和调试

// 测试工具类型
type Expect<T extends true> = T;
type Equal<X, Y> = 
  (<T>() => T extends X ? 1 : 2) extends 
  (<T>() => T extends Y ? 1 : 2) ? true : false;

// 测试用例
type Test = Expect<Equal<1, 1>>;

// 调试类型
type Debug<T> = { [K in keyof T]: T[K] };
type Prettify<T> = {
  [K in keyof T]: T[K];
} & {};

9. 现代 TypeScript 特性

模板字面量类型

type World = "world";
type Greeting = `hello ${World}`; // "hello world"

type Color = "red" | "blue";
type Size = "small" | "large";
type ButtonStyle = `${Size}-${Color}-button`; 
// "small-red-button" | "small-blue-button" | "large-red-button" | "large-blue-button"

satisfies 运算符

const theme = {
  primary: '#ff0000',
  secondary: '#00ff00',
  borderRadius: '8px'
} satisfies Record<string, string>;

// theme.borderRadius 是 string 类型,但值被约束

10. 实战模式

函数式编程模式

// 柯里化
type Curried<T, R> = T extends []
  ? R
  : T extends [infer First, ...infer Rest]
  ? (arg: First) => Curried<Rest, R>
  : never;

function curry<T extends any[], R>(fn: (...args: T) => R): Curried<T, R> {
  return function curried(...args: any[]): any {
    return args.length >= fn.length
      ? fn(...args)
      : (...moreArgs: any[]) => curried(...args, ...moreArgs);
  } as any;
}

要真正精通 TypeScript,建议:

  1. 深入理解类型系统 - 掌握泛型、条件类型、映射类型等高级特性
  2. 实践项目 - 在真实项目中应用 TypeScript
  3. 阅读源码 - 学习优秀的 TypeScript 项目源码
  4. 关注更新 - TypeScript 每个版本都有新特性
  5. 工具链熟练 - 掌握 ESLint、Prettier、构建工具等

需要我详细解释某个特定方面吗?

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐