ts 基础知识总结

发布于:2025-07-31 ⋅ 阅读:(19) ⋅ 点赞:(0)

TypeScript 日常工作笔记

1. 基础类型

1.1 基本类型

解释: TypeScript 提供了比 JavaScript 更丰富的类型系统。

// 基本类型
let str: string = "hello";           // 字符串
let num: number = 42;               // 数字
let bool: boolean = true;           // 布尔值
let n: null = null;                 // null
let u: undefined = undefined;       // undefined
let sym: symbol = Symbol("id");     // Symbol
let big: bigint = 123n;             // BigInt

// 数组类型
let arr1: number[] = [1, 2, 3];     // 数字数组
let arr2: Array<string> = ["a", "b"]; // 字符串数组

// 元组类型
let tuple: [string, number] = ["张三", 25]; // 固定长度和类型的数组

// 枚举类型
enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}
let color: Color = Color.Red;

1.2 对象类型

解释: 对象类型定义了对象的结构和属性类型。

// 对象类型定义
interface Person {
  name: string;
  age: number;
  email?: string; // 可选属性
  readonly id: number; // 只读属性
}

// 使用接口
const person: Person = {
  name: "张三",
  age: 25,
  id: 1
};

// 类型别名
type Point = {
  x: number;
  y: number;
};

// 联合类型
type Status = "pending" | "success" | "error";
let status: Status = "pending";

// 交叉类型
type Employee = Person & {
  department: string;
  salary: number;
};

1.3 函数类型

解释: TypeScript 可以为函数参数和返回值指定类型。

// 函数类型定义
function add(a: number, b: number): number {
  return a + b;
}

// 箭头函数类型
const multiply: (a: number, b: number) => number = (a, b) => a * b;

// 函数接口
interface MathFunc {
  (a: number, b: number): number;
}

// 可选参数和默认参数
function greet(name: string, greeting: string = "Hello"): string {
  return `${greeting}, ${name}!`;
}

// 剩余参数
function sum(...numbers: number[]): number {
  return numbers.reduce((acc, num) => acc + num, 0);
}

// 函数重载
function process(value: string): string;
function process(value: number): number;
function process(value: string | number): string | number {
  if (typeof value === "string") {
    return value.toUpperCase();
  } else {
    return value * 2;
  }
}

2. 高级类型

2.1 泛型

解释: 泛型允许创建可重用的组件,这些组件可以处理多种类型。

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

const result1 = identity<string>("hello");
const result2 = identity(42); // 类型推断

// 泛型接口
interface Container<T> {
  value: T;
  getValue(): T;
}

// 泛型类
class Queue<T> {
  private data: T[] = [];

  push(item: T): void {
    this.data.push(item);
  }

  pop(): T | undefined {
    return this.data.shift();
  }
}

const stringQueue = new Queue<string>();
stringQueue.push("hello");

2.2 条件类型

解释: 条件类型根据输入类型选择输出类型。

// 基本条件类型
type NonNullable<T> = T extends null | undefined ? never : T;

type T1 = NonNullable<string | number | null>; // string | number

// 条件类型与 infer
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

type FuncReturnType = ReturnType<() => string>; // string

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

type Required<T> = {
  [P in keyof T]-?: T[P];
};

type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

// 使用示例
interface User {
  name: string;
  age: number;
  email?: string;
}

type PartialUser = Partial<User>; // 所有属性变为可选
type RequiredUser = Required<User>; // 所有属性变为必需
type ReadonlyUser = Readonly<User>; // 所有属性变为只读

2.3 工具类型

解释: TypeScript 提供了许多内置的工具类型。

// Pick - 选择部分属性
type UserBasic = Pick<User, 'name' | 'age'>;

// Omit - 排除部分属性
type UserWithoutEmail = Omit<User, 'email'>;

// Record - 创建键值对类型
type UserRoles = Record<string, string[]>;

// Exclude - 排除联合类型中的某些类型
type NonNull = Exclude<string | number | null, null>; // string | number

// Extract - 提取联合类型中的某些类型
type StringOrNumber = Extract<string | number | boolean, string | number>; // string | number

// Parameters - 获取函数参数类型
type FuncParams = Parameters<(name: string, age: number) => void>; // [string, number]

// InstanceType - 获取构造函数实例类型
class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}
type AnimalInstance = InstanceType<typeof Animal>; // Animal

3. 接口与类型

3.1 接口扩展

解释: 接口可以继承和扩展其他接口。

// 基本接口
interface Shape {
  color: string;
}

// 接口扩展
interface Square extends Shape {
  sideLength: number;
}

// 多接口扩展
interface Circle extends Shape {
  radius: number;
}

interface ColoredCircle extends Circle {
  borderColor: string;
}

// 实现接口
class MySquare implements Square {
  constructor(public color: string, public sideLength: number) {}
}

// 接口合并
interface Box {
  height: number;
  width: number;
}

interface Box {
  scale: number;
}

// 最终 Box 接口包含 height, width, scale 三个属性

3.2 类型别名

解释: 类型别名可以为类型创建新名称。

// 基本类型别名
type Name = string;
type Age = number;
type UserId = string | number;

// 联合类型别名
type Status = "loading" | "success" | "error";

// 函数类型别名
type EventHandler = (event: Event) => void;
type AsyncFunction<T> = () => Promise<T>;

// 对象类型别名
type Point = {
  x: number;
  y: number;
};

// 映射类型别名
type Optional<T> = {
  [K in keyof T]?: T[K];
};

// 条件类型别名
type IsString<T> = T extends string ? true : false;

4. 类与面向对象

4.1 类定义

解释: TypeScript 的类支持访问修饰符、抽象类等特性。

// 基本类
class Animal {
  private name: string;
  protected age: number;
  public species: string;

  constructor(name: string, age: number, species: string) {
    this.name = name;
    this.age = age;
    this.species = species;
  }

  public makeSound(): void {
    console.log("Some sound");
  }

  protected getInfo(): string {
    return `${this.name} is ${this.age} years old`;
  }
}

// 继承
class Dog extends Animal {
  private breed: string;

  constructor(name: string, age: number, breed: string) {
    super(name, age, "Dog");
    this.breed = breed;
  }

  public makeSound(): void {
    console.log("Woof!");
  }

  public getBreedInfo(): string {
    return `${this.getInfo()}, breed: ${this.breed}`;
  }
}

// 抽象类
abstract class Vehicle {
  abstract start(): void;

  stop(): void {
    console.log("Vehicle stopped");
  }
}

class Car extends Vehicle {
  start(): void {
    console.log("Car started");
  }
}

4.2 访问修饰符

解释: TypeScript 提供了三种访问修饰符来控制类成员的可见性。

class Example {
  public publicField: string = "public";     // 任何地方都可以访问
  private privateField: string = "private";  // 只能在类内部访问
  protected protectedField: string = "protected"; // 只能在类内部和子类中访问

  public publicMethod(): void {
    console.log(this.privateField); // 可以访问私有成员
  }

  private privateMethod(): void {
    console.log("private method");
  }

  protected protectedMethod(): void {
    console.log("protected method");
  }
}

class SubExample extends Example {
  public test(): void {
    console.log(this.publicField);     // 可以访问
    console.log(this.protectedField);  // 可以访问
    // console.log(this.privateField); // 错误:不能访问私有成员
  }
}

5. 模块与命名空间

5.1 模块导入导出

解释: TypeScript 支持 ES6 模块语法,可以导入导出类型和值。

// math.ts - 导出模块
export interface Point {
  x: number;
  y: number;
}

export function add(a: number, b: number): number {
  return a + b;
}

export const PI = 3.14159;

export default class Calculator {
  add(a: number, b: number): number {
    return a + b;
  }
}

// main.ts - 导入模块
import Calculator, { add, PI, Point } from './math';

const calc = new Calculator();
const result = calc.add(5, 3);
const point: Point = { x: 10, y: 20 };

// 重命名导入
import { add as addNumbers } from './math';

// 导入所有内容
import * as MathUtils from './math';

5.2 命名空间

解释: 命名空间提供了一种组织代码的方式,避免全局命名空间污染。

// 基本命名空间
namespace Validation {
  export interface StringValidator {
    isValid(s: string): boolean;
  }

  export class EmailValidator implements StringValidator {
    isValid(s: string): boolean {
      return s.includes('@');
    }
  }

  export class PhoneValidator implements StringValidator {
    isValid(s: string): boolean {
      return /^\d{11}$/.test(s);
    }
  }
}

// 使用命名空间
const emailValidator = new Validation.EmailValidator();
const isValid = emailValidator.isValid("test@example.com");

// 嵌套命名空间
namespace Geometry {
  export namespace Shapes {
    export class Circle {
      constructor(public radius: number) {}

      area(): number {
        return Math.PI * this.radius ** 2;
      }
    }
  }
}

const circle = new Geometry.Shapes.Circle(5);

6. 类型断言与类型守卫

6.1 类型断言

解释: 类型断言告诉 TypeScript 编译器你比它更了解某个值的类型。

// 基本类型断言
let someValue: unknown = "this is a string";
let strLength: number = (someValue as string).length;

// 另一种语法
let strLength2: number = (<string>someValue).length;

// 非空断言
function processName(name?: string) {
  console.log(name!.toUpperCase()); // 断言 name 不为 null/undefined
}

// 类型断言函数
function isString(value: unknown): value is string {
  return typeof value === "string";
}

function processValue(value: unknown) {
  if (isString(value)) {
    console.log(value.toUpperCase()); // TypeScript 知道 value 是 string
  }
}

6.2 类型守卫

解释: 类型守卫是运行时检查,用于缩小类型范围。

// typeof 类型守卫
function process(value: string | number) {
  if (typeof value === "string") {
    return value.toUpperCase();
  } else {
    return value.toFixed(2);
  }
}

// instanceof 类型守卫
class Dog {
  bark() {
    return "Woof!";
  }
}

class Cat {
  meow() {
    return "Meow!";
  }
}

function makeSound(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    return animal.bark();
  } else {
    return animal.meow();
  }
}

// in 操作符类型守卫
interface Bird {
  fly(): void;
  layEggs(): void;
}

interface Fish {
  swim(): void;
  layEggs(): void;
}

function move(animal: Bird | Fish) {
  if ("fly" in animal) {
    animal.fly();
  } else {
    animal.swim();
  }
}

7. 实用类型技巧

7.1 条件类型与映射

解释: 结合条件类型和映射类型可以创建强大的类型工具。

// 深度可选
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];
};

// 提取函数参数类型
type Parameters<T> = T extends (...args: infer P) => any ? P : never;

// 提取函数返回类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

// 提取 Promise 类型
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;

// 使用示例
interface User {
  name: string;
  profile: {
    age: number;
    email: string;
  };
}

type PartialUser = DeepPartial<User>;
// 等价于:
// {
//   name?: string;
//   profile?: {
//     age?: number;
//     email?: string;
//   };
// }

7.2 模板字面量类型

解释: TypeScript 4.1+ 支持模板字面量类型,可以基于字符串字面量创建类型。

// 基本模板字面量类型
type Greeting = "Hello" | "Hi" | "Welcome";
type Name = "World" | "TypeScript" | "Developer";
type GreetingMessage = `${Greeting} ${Name}!`;

// 字符串操作类型
type Uppercase<S extends string> = S extends `${infer F}${infer R}`
  ? `${Uppercase<F>}${Uppercase<R>}`
  : S;

type Lowercase<S extends string> = S extends `${infer F}${infer R}`
  ? `${Lowercase<F>}${Lowercase<R>}`
  : S;

// 字符串替换
type Replace<S extends string, From extends string, To extends string> = 
  S extends `${infer Prefix}${From}${infer Suffix}`
    ? `${Prefix}${To}${Suffix}`
    : S;

// 使用示例
type EventName = "click" | "hover" | "focus";
type HandlerName = `on${Capitalize<EventName>}`;
// 结果: "onClick" | "onHover" | "onFocus"

8. 错误处理与调试

8.1 严格模式

解释: TypeScript 的严格模式可以帮助捕获更多潜在错误。

// tsconfig.json 中的严格选项
{
  "compilerOptions": {
    "strict": true,                    // 启用所有严格检查
    "noImplicitAny": true,            // 禁止隐式 any
    "strictNullChecks": true,         // 严格的 null 检查
    "strictFunctionTypes": true,      // 严格的函数类型检查
    "strictBindCallApply": true,      // 严格的 bind/call/apply 检查
    "strictPropertyInitialization": true, // 严格的属性初始化检查
    "noImplicitReturns": true,        // 禁止隐式返回
    "noFallthroughCasesInSwitch": true, // 禁止 switch 中的 fallthrough
    "noUncheckedIndexedAccess": true  // 禁止未检查的索引访问
  }
}

// 严格 null 检查示例
function processName(name: string | null) {
  if (name === null) {
    return "Anonymous";
  }
  return name.toUpperCase(); // TypeScript 知道 name 不是 null
}

8.2 类型错误处理

解释: 处理 TypeScript 编译错误的最佳实践。

// 使用类型断言处理第三方库
declare const externalLib: any;
const data = externalLib.getData() as MyDataType;

// 使用 unknown 类型
function processUnknownData(data: unknown) {
  if (typeof data === "object" && data !== null) {
    const obj = data as Record<string, unknown>;
    if ("name" in obj && typeof obj.name === "string") {
      console.log(obj.name.toUpperCase());
    }
  }
}

// 使用 satisfies 操作符(TypeScript 4.9+)
const config = {
  apiUrl: "https://api.example.com",
  timeout: 5000,
  retries: 3
} satisfies ApiConfig;

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

9. 项目实践

9.1 类型定义文件

解释: 为第三方库或项目创建类型定义。

// types/global.d.ts
declare global {
  interface Window {
    myCustomProperty: string;
  }

  namespace NodeJS {
    interface ProcessEnv {
      NODE_ENV: "development" | "production" | "test";
      API_URL: string;
    }
  }
}

export {};

// types/api.d.ts
export interface ApiResponse<T = any> {
  success: boolean;
  data: T;
  message: string;
  code: number;
}

export interface PaginatedResponse<T> extends ApiResponse<T[]> {
  pagination: {
    page: number;
    pageSize: number;
    total: number;
    totalPages: number;
  };
}

// types/user.d.ts
export interface User {
  id: number;
  name: string;
  email: string;
  avatar?: string;
  createdAt: string;
  updatedAt: string;
}

export interface CreateUserRequest {
  name: string;
  email: string;
  password: string;
}

export interface UpdateUserRequest extends Partial<CreateUserRequest> {
  id: number;
}

9.2 实用工具类型

解释: 创建项目中常用的工具类型。

// utils/types.ts
// 提取 API 响应类型
type ApiResponseType<T> = T extends Promise<ApiResponse<infer U>> ? U : never;

// 提取表单字段类型
type FormFields<T> = {
  [K in keyof T]: T[K] extends string | number | boolean ? T[K] : never;
};

// 创建表单验证规则类型
type ValidationRules<T> = {
  [K in keyof T]?: {
    required?: boolean;
    min?: number;
    max?: number;
    pattern?: RegExp;
    message?: string;
  };
};

// 提取事件处理函数类型
type EventHandler<T> = (event: T) => void;

// 创建状态类型
type LoadingState = "idle" | "loading" | "success" | "error";

type StateWithLoading<T> = {
  data: T | null;
  loading: LoadingState;
  error: string | null;
};

// 使用示例
interface UserForm {
  name: string;
  email: string;
  age: number;
}

type UserFormFields = FormFields<UserForm>;
type UserValidationRules = ValidationRules<UserForm>;

10. 常见问题与解决方案

10.1 类型推断问题

// 问题:类型推断不准确
const items = [1, 2, 3, "hello"]; // 推断为 (number | string)[]

// 解决方案:明确类型
const items: number[] = [1, 2, 3];
const mixedItems: (number | string)[] = [1, 2, 3, "hello"];

10.2 泛型约束

// 问题:泛型类型过于宽泛
function getProperty<T>(obj: T, key: string) {
  return obj[key]; // 错误:不能保证 key 存在于 obj 中
}

// 解决方案:添加约束
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

10.3 异步函数类型

// 问题:异步函数返回类型不明确
async function fetchData() {
  const response = await fetch('/api/data');
  return response.json(); // 返回 any
}

// 解决方案:明确返回类型
async function fetchData(): Promise<User[]> {
  const response = await fetch('/api/data');
  return response.json();
}

本笔记涵盖了 TypeScript 的核心概念和实用技巧,适合日常开发查阅。建议结合官方文档和实际项目实践深入学习。


网站公告

今日签到

点亮在社区的每一天
去签到