概述

TypeScript Utility Types(实用工具类)包含一系列预定义的类型,用于简化类型操作,善用这些类型可以让我们的代码更加简洁优雅,今天来学习一下Omit类型。Omit类型可以优雅的解决类型重复问题,避免冗余代码。

Omit类型的作用是什么?与以往不同,我们先不介绍晦涩难懂的概念,而是从一个实际的例子出发,进而引出这个类型。

从类型中排除属性

考虑下面这个常见的场景,你正在开发一个用户管理系统,这个系统的一个重要功能就是管理用户,比如创建用户,更新用户信息,删除用户等。

为了支持以上操作,我们首先要定义一个用户类型User,下面就是这个User类型的定义:其中包括用户id,姓名,手机号和邮箱。

interface User {
id: number; // 用户ID
name: string; // 用户名
phone: string; // 手机号
email: string; // 邮箱
}

首先:我们编写创建用户的函数,这个函数需要接收一个User类型的参数,并调用后端API来创建用户。

function createUser(user: User) {
// 调用后端API来创建用户
api.createUser(user).then(response => {
console.log('User created:', response.data);
}).catch(error => {
console.error('Error creating user:', error);
});
}

接下来,我们编写更新用户信息的函数,这个函数需要接收一个User类型的参数,并调用后端API来更新用户信息。

function updateUser(user: User) {
// 调用后端API来更新用户信息
api.updateUser(user).then(response => {
console.log('User updated:', response.data);
}).catch(error => {
console.error('Error updating user:', error);
});
}

删除用户的函数我们就不写了,因为它不影响我们今天的主题。

到现在为止,似乎一切都很顺利,创建用户和更新用户的函数使用同一个User类型,代码也很简洁。

但是,这里有一个小问题,那就是在创建用户的时候,其实我们并不需要提供用户的id,因为只有用户创建成功之后才会生成这个id。虽然说多传一个id属性不会报错,但是从逻辑上来说,这个id属性是多余的。作为一个有追求的程序员,不能容忍这种冗余代码的存在。

于是有的同学说:这还不简单吗?再定一个类型用于创建用户,把id属性去掉不就行了?于是就有了下面的NewUser类型。

interface NewUser {
name: string;
phone: string;
email: string;
}

但是,这样做有一个问题, NewUser类型和User类型几乎一模一样,除了id属性外,其他字段都是重复的,这就是典型的冗余代码,对于日后的维护十分不便。

设想一下,假如某一天需要为用户添加一个新的属性,比如address,那么我们就需要在UserNewUser两个类型中都添加这个属性,维护起来非常麻烦,删除某个属性也面临同样的问题。

有没有更好的办法呢?这时候,Omit类型就派上用场了,Omit类型允许我们从一个类型中排除某些属性,从而创建一个新的类型。

下面这段代码表示:创建一个新类型NewUser,它是从User类型中排除掉id属性后的结果。

type NewUser = Omit<User, 'id'>;

现在,我们可以使用NewUser类型来创建用户了。

function createUser(user: NewUser) {
// 调用后端API来创建用户
api.createUser(user).then(response => {
console.log('User created:', response.data);
}).catch(error => {
console.error('Error creating user:', error);
});
}

如果某一天需要为用户添加一个新的属性,比如address,我们只需要在User类型中添加这个属性,而不需要修改NewUser类型,这样就避免了冗余代码的出现。删除某个属性也同样方便。

更方便的是,Omit一次可以排除多个属性,比如我们还想排除email属性,可以这样写:

type NewUser = Omit<User, 'id' | 'email'>;

这样,NewUser类型就会同时排除idemail属性。

写到这里,似乎该结束了,但是作为一个有追求的程序员,你以为这就完了吗?当然不行,我们要举一反三,如果反过来该怎么办呢?

向类型中添加属性

假设你维护的是一个老系统,原来的代码先定义了NewUser类型(只有创建用户的需求),现在添加了一个新需求:要求添加一个函数用于更新用户的信息,更新用户信息就需要提供用户ID,这时候你需要一个新的类型,也就是在NewUser的基础上添加id属性。通俗点说,前面的例子是在一个类型中排除某些属性,而现在我们需要在一个类型中添加某些属性。这相当于Omit的反向操作。

那TypeScript中有没有这样的实用类型呢?非常遗憾,TypeScript的标准库中并没有提供这样的类型,但是我们可以自己实现一个。

下面的代码使用&操作符来创建一个新的类型UpdateUser,它包含了NewUser的所有属性,并添加了一个id属性。

type UpdateUser = NewUser & { id: number };

这样,我们就可以使用UpdateUser类型来更新用户信息了。

function updateUser(user: UpdateUser) {
// 调用后端API来更新用户信息
api.updateUser(user).then(response => {
console.log('User updated:', response.data);
}).catch(error => {
console.error('Error updating user:', error);
});
}

是不是很优雅呢?你学会了吗?学会了就点个关注吧,后续会有更多有趣的TypeScript知识分享。

参考

  1. https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys

TypeScript实用类型之Omit的更多相关文章

  1. 编写TypeScript工具类型,你需要知道的知识

    什么是工具类型 用 JavaScript 编写中大型程序是离不开 lodash 工具的,而用 TypeScript 编程同样离不开工具类型的帮助,工具类型就是类型版的 lodash .简单的来说,就是 ...

  2. TypeScript 条件类型精读与实践

    在大多数程序中,我们必须根据输入做出决策.TypeScript 也不例外,使用条件类型可以描述输入类型与输出类型之间的关系. 本文同步首发在个人博客中,欢迎订阅.交流. 用于条件判断时的 extend ...

  3. C# vs TypeScript - 高级类型

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  4. 从C#到TypeScript - 高级类型

    C# vs TypeScript - 高级类型 上一篇讲了基础类型,基本上用基础类型足够开发了,不过如果要更高效的开发,还是要看下高级类型,这篇和C#共同点并不多,只是延用这个主题. 联合类型 可以从 ...

  5. TypeScript 之类型判断

    在使用 Angular 做项目的时候,对 TypeScript 的类型判断不太熟练,为了方便查找,特意对 TypeScript 的类型判断做了简单梳理.文章只是 TS 官网的内容摘要,没有高深的知识, ...

  6. TypeScript的类型

    ⒈TypeScript的类型 JavaScript语言的数据类型包括以下7种: 1.boolean(布尔),true || false 2.null,表明null值得特殊关键字,JavaScript是 ...

  7. TypeScript入门三:TypeScript函数类型

    TypeScript函数类型 TypeScript函数的参数 TypeScript函数的this与箭头函数 TypeScript函数重载 一.TypeScript函数类型 在上一篇博客中已经对声明Ty ...

  8. React 与 Hooks 如何使用 TypeScript 书写类型?

    React 与 Hooks 如何使用 TypeScript 书写类型? 本文写于 2020 年 9 月 20 日 函数组件与 TS 对于 Hooks 来说是不支持使用 class 组件的. 如何在函数 ...

  9. TypeScript 高级类型

    ⒈交叉类型(Intersection Types) 交叉类型是将多个类型合并为一个类型. 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性. 例如, Person &a ...

  10. Typescript基础类型

    1.布尔值__boolean 2.数字__number----除了支持十进制和十六进制字面量,Typescript还支持ECMAScript 2015中引入的二进制和八进制字面量. 3.字符串__st ...

随机推荐

  1. Linux系统挂载未分配硬盘空间

    先查看未挂载之前的磁盘使用情况 发现磁盘使用率已经达到了96%,迫切需要扩容 查看分区情况fdisk –l 首先确保有可分配的磁盘空间 发现/dev/vda下有400多个G 的空间 所以将/dev/v ...

  2. Linux-两台Linux服务器间设置共享文件夹(NFS服务器)

    一.环境信息服务器1:192.168.120.141        文件夹:/opt服务器2:192.168.120.142        文件夹:/opt将服务器1的/opt文件夹共享到服务器2的/ ...

  3. 【Java】字符串常用操作

    字符的常用技巧 char c; 字母的顺序:c - 'A'.c - 'a' 字母大小写转换:c - 'a' + 'A'.c - 'A' + 'a' 数字字符转换为数字:c - '0' String.S ...

  4. Python字典及基本操作(超级详细)

    今天小张帮大家简单介绍下Python的一种数据结构: 字典,字典是 Python 提供的一种常用的数据结构,它用于存放具有映射关系的数据. 比如有份成绩表数据,语文:79,数学:80,英语:92,这组 ...

  5. Python科学计算系列1—方程和方程组

    1.一元方程求解 例1:求下列一元二次方程的解 代码如下: # 定义数学符号 from sympy import symbols, solve x = symbols('x') f = x ** 2 ...

  6. 机器人操作系统ROS2之简介

    什么是ROS2? ROS(机器人操作系统)是用于机器人应用的开源软件开发工具包.ROS 为各行业的开发者提供了一个标准的软件平台,帮助他们从研究和原型设计一直推进到部署和生产,从驱动程序到最先进的算法 ...

  7. Go 语言的数据类型转换有哪些?

    当不同的数据类型相互操作的时候,就需要类型转换,Go 的数据类型转换还是比较简单的. 数据类型转换包含显式和隐式两类,隐式的一般是大的数据类型到小的类型进行转换,不会有精度丢失的问题.否则就需要进行显 ...

  8. 2025dsfz集训Day3:DFS搜索与剪枝

    DAY3: DFS搜索与剪枝 \[Designed\ By\ FrankWkd\ -\ Luogu@Lwj54joy,uid=845400 \] 特别感谢 此次课的主讲 - Kwling 深搜 深度优 ...

  9. [开源] .Net 使用 ORM 访问 神舟通用数据库(神通)

    前言 天津神舟通用数据技术有限公司(简称"神舟通用公司"),隶属于中国航天科技集团(CASC).是国内从事数据库.大数据解决方案和数据挖掘分析产品研发的专业公司.公司获得了国家核高 ...

  10. Linux操作系统(中)

    上一篇分享了一些Linux操作系统最基本的一些命令和基础知识,下面,要分享的还是Linux操作系统的一些内容,因为在做网安这方面,Linux会经常用到而且也很重要,好了,废话不多说,要开始了. 在Li ...