TS 高级类型:Partial 使用及实现原理

面试导航 是一个专注于前、后端技术学习和面试准备的 免费 学习平台,提供系统化的技术栈学习,深入讲解每个知识点的核心原理,帮助开发者构建全面的技术体系。平台还收录了大量真实的校招与社招面经,帮助你快速掌握面试技巧,提升求职竞争力。如果你想加入我们的交流群,欢迎通过微信联系:yunmz777

在用 TypeScript 写项目的时候,难免会碰到各种类型之间需要转换的情况。比如某个对象类型,我们只想用它的一部分,或者想让它的属性变成可选的。这时候,TS 自带的工具类型就非常好用!

这个系列我们就来聊聊那些常用的 TS 内置工具类型,让你写类型更轻松、更优雅。

第一位登场的是------Partial

什么是 Partial

在 TypeScript 中,Partial 是一个非常实用的工具类型(Utility Type),它的作用就是:把某个类型的所有属性变成可选的。

换句话说,如果你原本有一个类型里所有字段都是必填的,用 Partial 包一下之后,就可以只写其中一部分字段了,非常适合用在更新、配置等场景中。

它的定义如下:

ts 复制代码
type Partial<T> = {
  [P in keyof T]?: T[P];
};

✨ 应用场景

Partial 在实际开发中非常常见,尤其适用于以下几个场景:

  1. 处理部分更新:比如你有一个完整的用户类型,但在更新时,往往只需要改一两个字段。这时候就不需要手动把每个字段都变成可选了,直接用 Partial<User> 更方便。

  2. 设置默认值再覆盖:有时候你会先定义一份默认配置,然后根据用户传入的值来覆盖。使用 Partial 可以让这些覆盖的属性不是必填的。

  3. 配置对象参数:当你写的函数接受一个配置对象作为参数,但又不希望强制调用方提供所有配置项,Partial 就很适合让这些参数都变成可选的。

🔧 基本使用

来看一个简单的例子:

ts 复制代码
interface User {
  id: number;
  name: string;
  age: number;
}

现在我们有一个完整的用户对象:

ts 复制代码
const user: User = {
  id: 1,
  name: "Moment",
  age: 18,
};

接下来我们写一个更新函数,只更新用户的部分信息:

ts 复制代码
function updateUser(user: User, updatedProperties: Partial<User>): User {
  return { ...user, ...updatedProperties };
}

const updatedUser = updateUser(user, { age: 20 });
console.log(updatedUser); // { id: 1, name: 'Moment', age: 20 }

你会发现,只传入了 age 字段,也能成功更新。这就是 Partial 的魅力。

✅ 不用手动把 nameid 标成可选,TypeScript 自动帮你搞定了。

最终运行结果如下图所示:

🧠 实现原理

Partial 的实现,其实用到了 TypeScript 中两个核心特性:映射类型(Mapped Types) 和 索引类型(Index Types)。

首先我们对 Partial 的定义回顾:

ts 复制代码
type Partial<T> = {
  [P in keyof T]?: T[P];
};

逐步拆解来看:

  • keyof T:取出类型 T 的所有键,例如 User 的话就是 'id' | 'name' | 'age'

  • [P in keyof T]:对这些键进行遍历,也就是"映射"。

  • ?: T[P]:将每个属性变成可选,且类型保持原样。

我们再来对索引类型简单回顾:

ts 复制代码
interface User {
  id: number;
  name: string;
  age: number;
}

type UserKeys = keyof User; // 'id' | 'name' | 'age'
type UserIdType = User["id"]; // number

结合这两个特性,Partial 就能把一个类型"转换"为一个所有字段都可选的新类型,而你只需要一行代码就能搞定,非常方便。

复杂场景:表单编辑(Form 编辑场景)

假设你正在开发一个用户管理系统,用户的资料可以编辑,但不一定每次都更新所有字段,而且用户资料的结构比较复杂,包含嵌套对象。

用户类型定义:

ts 复制代码
interface Address {
  city: string;
  street: string;
}

interface UserProfile {
  id: number;
  name: string;
  age: number;
  email: string;
  address: Address;
}

你现在有一个编辑页面,只需要让用户填写他们想更新的字段,比如修改邮箱、改地址,但不强制填写所有信息。这时候如果你直接用 UserProfile,就会强制所有字段都必填,非常不灵活。

于是,你可以写一个更新函数,使用 Partial 来支持"只更新部分字段"的能力:

ts 复制代码
function updateProfile(
  profile: UserProfile,
  updates: Partial<UserProfile>
): UserProfile {
  return {
    ...profile,
    ...updates,
    // 注意:如果 updates.address 存在,也需要做浅合并
    address: {
      ...profile.address,
      ...updates.address,
    },
  };
}

如下使用示例:

ts 复制代码
const originalProfile: UserProfile = {
  id: 1,
  name: "Moment",
  age: 30,
  email: "[email protected]",
  address: {
    city: "Shanghai",
    street: "中山街道",
  },
};

// 只修改 email 和 address.city
const updated = updateProfile(originalProfile, {
  email: "[email protected]",
  address: {
    city: "Beijing",
  },
});

console.log(updated);
// 输出:
// {
//   id: 1,
//   name: "Alice",
//   age: 30,
//   email: "[email protected]",
//   address: {
//     city: "Beijing",
//     street: "123 Main St",
//   }
// }

总结

Partial<T> 是 TypeScript 提供的工具类型,用于将某个类型的所有属性变为可选。它非常适合用于处理对象的部分更新配置对象参数默认值合并 等场景。使用 Partial 可以让代码更灵活,避免手动修改每个字段为可选。它的实现基于映射类型和索引类型,是 TS 类型系统中最常用也最基础的工具之一。

相关推荐
小兔崽子去哪了4 分钟前
微信小程序入门
前端·vue.js·微信小程序
独立开阀者_FwtCoder7 分钟前
# 白嫖千刀亲测可行——200刀拿下 Cursor、V0、Bolt和Perplexity 等等 1 年会员
前端·javascript·面试
不和乔治玩的佩奇14 分钟前
【 React 】useState (温故知新)
前端
那小孩儿14 分钟前
?? 、 || 、&&=、||=、??=这些运算符你用对了吗?
前端·javascript
七月十二17 分钟前
[微信小程序]对接sse接口
前端·微信小程序
小七_雪球19 分钟前
Permission denied"如何解决?详解GitHub SSH密钥认证流程
前端·github
野原猫之助20 分钟前
tailwind css在antd组件中使用不生效
前端
菜鸟码农_Shi23 分钟前
Node.js 如何实现 GitHub 登录(OAuth 2.0)
javascript·node.js
没资格抱怨27 分钟前
如何在vue3项目中使用 AbortController取消axios请求
前端·javascript·vue.js
掘金酱31 分钟前
😊 酱酱宝的推荐:做任务赢积分“拿”华为MatePad Air、雷蛇机械键盘、 热门APP会员卡...
前端·后端·trae