当前位置: 首页 > news >正文

TS常见内置映射类型的实现及应用场景

以下是 TypeScript 在前端项目中 常用的映射类型(Mapped Types),结合具体场景和代码示例,帮助开发者高效处理复杂类型:


一、基础映射类型

1. Partial<T>

作用:将对象类型 T 的所有属性变为可选。
实现

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

应用场景

  • 表单的初始状态(部分字段可选)。

  • API 请求的更新参数(只需传部分字段)。

interface User {
  name: string;
  age: number;
}

type PartialUser = Partial<User>;
// { name?: string; age?: number }

const initialForm: PartialUser = {}; // 合法

2. Required<T>

作用:将对象类型 T 的所有属性变为必填。
实现

type Required<T> = {
  [P in keyof T]-?: T[P]; // "-?" 表示移除可选修饰符
};

应用场景

  • 严格校验配置对象(确保所有字段必须存在)。

type StrictConfig = Required<{ apiUrl?: string }>;
// { apiUrl: string }

const config: StrictConfig = { apiUrl: "https://api.com" }; // 必须填写

3. Readonly<T>

作用:将对象类型 T 的所有属性变为只读。
实现

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

应用场景

  • 全局常量配置(防止意外修改)。

  • React 组件的默认 Props。

const defaultProps: Readonly<{ color: string }> = { color: "red" };
defaultProps.color = "blue"; // 编译报错:只读属性

4. Pick<T, K>

作用:从对象类型 T 中选取指定键 K 的子集。
实现

type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

应用场景

  • 组件 Props 的透传(如仅暴露部分属性)。

  • 过滤敏感字段(如排除 password)。

interface User {
  id: string;
  name: string;
  password: string;
}

type SafeUser = Pick<User, "id" | "name">;
// { id: string; name: string }

5. Omit<T, K>

作用:从对象类型 T 中排除指定键 K 的属性。
实现

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

应用场景

  • 覆盖组件默认 Props。

  • 忽略不需要的 API 响应字段。

type UserWithoutPassword = Omit<User, "password">;
// { id: string; name: string }

6. Record<K, T>

作用:创建一个键类型为 K,值类型为 T 的对象类型。
实现

type Record<K extends keyof any, T> = {
  [P in K]: T;
};

应用场景

  • 枚举映射(如国际化词表)。

  • Redux 的 Action 类型集合。

type Language = "en" | "zh";
type I18N = Record<Language, { title: string }>;

const i18n: I18N = {
  en: { title: "Hello" },
  zh: { title: "你好" },
};

二、进阶映射类型

1. 条件映射:{ [K in keyof T]: T[K] extends U ? X : Y }

作用:根据条件筛选或转换属性类型。
应用场景

  • 提取所有函数属性。

  • 将数字属性转为字符串。

type FunctionKeys<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T]; // 最终得到联合类型

type UserMethods = FunctionKeys<User>; // "update" | "delete"

2. 深度映射:DeepReadonly / DeepPartial

作用:递归处理嵌套对象属性。
实现

type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object 
    ? DeepReadonly<T[K]> 
    : T[K];
};

type DeepPartial<T> = {
  [K in keyof T]?: T[K] extends object 
    ? DeepPartial<T[K]> 
    : T[K];
};

应用场景

  • 深度冻结状态(如 Redux 的不可变状态树)。

  • 表单的嵌套字段可选。

interface NestedData {
  user: { name: string; address: { city: string } };
}

type ReadonlyData = DeepReadonly<NestedData>;
// user 和 address 均为只读

3. 联合类型映射:{ [K in keyof T]: T[K] }

作用:将联合类型转为交叉类型或其他结构。
应用场景

  • 合并多个接口类型。

type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends (k: infer I) => void 
    ? I 
    : never;

type Combined = UnionToIntersection<{ a: 1 } | { b: 2 }>;
// { a: 1 } & { b: 2 }

三、前端实战场景

场景 1:动态表单控件 Props

根据表单字段类型生成对应的 UI 控件 Props。

type FieldType = "text" | "number" | "date";

type FieldProps<T extends FieldType> = {
  type: T;
  value: T extends "text" ? string :
         T extends "number" ? number :
         Date;
};

function renderField<T extends FieldType>(props: FieldProps<T>) {
  // 根据 type 渲染不同控件
}

场景 2:Redux Action 类型安全

自动推导 Action 类型,避免手动定义。

type ActionMap<M extends { [key: string]: any }> = {
  [Key in keyof M]: M[Key] extends undefined
    ? { type: Key }
    : { type: Key; payload: M[Key] };
};

type Actions = ActionMap<{
  LOGIN: { username: string };
  LOGOUT: undefined;
}>;

// 结果:
// { LOGIN: { type: "LOGIN"; payload: { username: string } }, 
//   LOGOUT: { type: "LOGOUT" } }

场景 3:组件 Props 动态扩展

通过映射类型动态生成复合 Props。

type WithClassName<T> = T & { className?: string };

type ButtonProps = WithClassName<{
  onClick: () => void;
  text: string;
}>;

// 结果:{ onClick: () => void; text: string; className?: string }

四、总结

映射类型核心能力典型场景
Partial<T>属性可选化表单初始值、更新参数
Pick<T, K> / Omit<T, K>属性筛选或排除组件 Props 透传
Record<K, T>键值对批量定义枚举映射、Action 集合
条件映射按条件转换属性类型动态表单控件
深度映射递归处理嵌套对象不可变状态、复杂表单

掌握这些映射类型后,可以大幅减少重复代码,提升前端项目的类型安全性和可维护性

相关文章:

  • Emacs 折腾日记(十七)——文本属性
  • Spark Sql 简单校验的实现
  • 大模型-提示词调优
  • 使用VSCode开发STM32补充(Debug调试)
  • Django连接MySQL
  • 徒手打造个人AI Agent:基于DeepSeek-R1+websearch从零构建类Manus深度探索智能体AI-Research
  • python爬虫Scrapy(5)之增量式
  • 使用Java调用Windows通知并显示自定义图标
  • 使用memmove优化插入排序
  • 【专项测试】限流测试
  • maven的安装配置
  • 【数据结构】线性表简介
  • 重要!!! 什么是梯度方差 ; AdaLoRA中的Fisher信息矩阵:核心作用与通俗举例
  • RUOYI框架在实际项目中的应用二:Ruoyi前后端分离版本
  • 【MySQL】(5) 数据行的增删改查操作
  • Hexo主题配置and常用指令
  • mysql-8.0.25-winx64安装步骤
  • 中考英语之02高频词汇
  • React 常用 Hooks 详细解析
  • 责任链模式
  • wordpress主题邮件模板下载失败/青岛seo精灵
  • 厦门市网站建设/百度企业查询
  • 车轮违章查询是什么网站开发/产品软文
  • 重庆企业网站开发服务/网站上不去首页seo要怎么办
  • 上海快速建站/百度问答app下载
  • django做网站/湖南网站建设seo