通过示例演示 TypeScript 的高级类型

原文地址: levelup.gitconnected.com/advanced-ty…
译文地址:github.com/xiao-T/note…
本文版权归原作者所有,翻译仅用于学习。


提升你对 TypeScript 的理解,并学这些高级的技术,可以帮助你掌握该语言并且可以更好的在 React 中使用 TypeScript。

去年冬天,我开始使用 TypeScript,我已经从一个使用 any 的新手逐渐成长为一个习惯使用高级内置类型和自定义类型的老手。通过在 JavaScript 代码添加类型判断,让应用变得更加健壮。这篇文章提供了一些使用高级类型的示例,也展示了如何在 React 应用使用它们。

在这里,我们将会探讨 RecordPartialRequiredPick 和一个自定义Omit 类型。

Record

Typescript 2.1 引入了一个非常有用的内置 type Record:它可以创建类型 map,而且,非常适合创建复合型的 interface。为了让变量成为 Record 类型,你需要传入一个字符串作为 key 和一些相关的 type。最简单情况是,你有一个 string 作为值的类型。

const SERVICES: Record<string, string> = { 
    doorToDoor: "delivery at door",
    airDelivery: "flying in",
    specialDelivery: "special delivery",
    inStore: "in-store pickup",
};

这显得微不足道,但是,它为你日常编码中提供更简单的方式定义类型。一种常见的情况是:当你需要把整个业务整体的 interface 作为键值对保存在字典中时,Record 就非常有用。这个 model 可以表示联系人、事件、用户数据、交通请求、电影票据等,各种集合。在接下来的演示中,我们为 product 创建了一个 model,用户可以添加到购物车:

你会看到编辑器是如何自动帮我们定义对象类型的,同时也会标记出错误提示,这是因为一些必要的属性没有定义:

另外,TypeScript 不允许我们为一些定义好的 type 创建空对象,需要提供相关的属性,但是,这时 Record 就有用处了。

另外,也可以用 string enum 作为 Record 的 key。例如,我们将会用 ErrorsEnum 来保存访问相关的错误信息:

我们来看看在 Material-UI 中它是如何增强类型的。就如指南中所说,你可以使用 CSS-in-JS 添加自定义的样式,然后,通过 withStyles HOC 注入。你可以通过一个函数定义样式,函数接受一个名 theme 的参数,然后,返回相关样式的 className,还可以为这个函数定义类型:

你应该注意到,因为每个样式对象添加了 as CSSProperties,所以变得非常麻烦。另外,你就可以使用 Record 带来的好处:定一个带有类型的 styles 函数:

现在,你可以在任何组件中安全的使用它,并且会摆脱明确定义 CSS properties 的束缚。

Partial and Required

Partial 可以让对象中所有的属性变成可选的。在很多情况它可以帮到你,比如,当你需要数据渲染组件时,但是,你知道在组件 mount 时并不会加载数据:

你还也可以用 Partial 来为组件定义默认的 props。

相反,TypeScript v2.8 中引入的 Required ,可以让对象中的所有的属性变成必选的:

Required 的用例之一就是 selectors:有时你想为嵌套对象中的属性创造选择器,并且,你知道在选择器调用时将会定义此属性。你可以为此指定一个类型:

这看起来像是作弊,如果,你从可选属性继承必选属性可能会引起类型错误,因此,要小心使用!

听起来很傻,但是,如果你的代码是自动生成的,并且,你所有的 interface 都是 Partial,UI 中所有的元素都是 Required,这种情况并不稀奇。这时你需要检查所有 undefined 的对象 😨。

Pick and Omit

曾经,你是否想过缩减一连串的类型,因为,你意识到下一个 class 并不需要这么多属性?或许你在重构时遇到这类问题,尝试以一种全新的方式分布系统的每一部分。这里有几种方式可以解决这类问题。

Pick 可以让你在一个已经定义好的 interface 中挑选你需要的 key。

Omit 在 TypeScript 的 lib.d.ts 中并没有预先定义,但是,它可以很容易通过 PickExclude 来定义。它可以从一个 interface 中排除掉你不想要的属性。

下面两张图片中,ProductPhotoProps 会包含 Product 所有的属性,name 和 descripition 除外:

其中一个实际示例,就来自我的项目:重构一个有着复杂依赖的庞大表单。有一个 FormProps 它包含了错误类型。重新思考后,对于第一个子组件这些错误类型并不是必要的,但是,第二个组件仍然需要。除了错误类型,我用 Pick 提取了一些属性构建了一个新的 interface,这种方式工作的很好。

当然,有多种方式可以合并类型和定义它们之间的关系。如果,从一开始你就把很大一块东西拆解成很多小块,你或许解决了从对象中排除属性的问题。但是,你会遇到扩展类型的问题。

继承扩展 type/interface

当你需要扩展一个 interface 时,所有的属性在新的 interface 都有效。我们来看看,如何合并多个小的 interface 以便符合的我们的任务需求:

这种方法并不是很方便,因为,你必须更有预见性考虑你的对象。从另一方面来讲,它更加快速和简单,让你设计原型或者构建简单 UI 更加炫酷,就像是把数据选到一个只读块中。

总结

通过一些真实代码,我已经介绍了比较流行的 TypeScript 内置的类型。这只是一个 demo,但是,我知道这所有的类型至少会在一个真实场景中有效😉。我希望这篇文章能帮助到你,并且,鼓励你不要害怕 TypeScript。我用 React-Redux 创建了一个 SPA 的代码仓,在这里你可以找到大多数的演示或者它们的替代方案。

然而,针对静态类型我还想多说一些。通常,当你探索一种新技术或者面对一个开发中的挑战时,你开始解决技术问题,反而忘记了你的目的。静态类型并不是你工作的目的,它只是一个工具。如果,它成为了项目中的核心,这代表着你已经走偏了🚀。记住要在业务和技术之间做好平衡,编码快乐!

原文链接:juejin.im

上一篇:ES2020新特性抢先看
下一篇:【踩坑之旅】Node.js 与 fsevents

相关推荐

  • 面向对象不是银弹,DDD 也不是,TypeScript 才是

    要解决的问题是什么? A problem well-stated is Half-solved Fred Brooks 在著名的"No Silver Bullet - Essence and Acci...

    1 年前
  • 重读《学习JavaScript数据结构与算法-第三版》-第2章 ECMAScript与TypeScript概述

    定场诗 八月中秋白露,路上行人凄凉; 小桥流水桂花香,日夜千思万想。 心中不得宁静,清早览罢文章, 十年寒苦在书房,方显才高志广。 前言 洛伊安妮·格罗纳女士所著的《学习JavaScript数据结构与...

    1 年前
  • 都用TypeScript,还不来分析Vue3源码(第一期)

    createApp 位置🍎:packages/compiler-core/src/apiCreateApp.ts 动机🍎:我们知道vue暴露了createAppAPI【位置packages/com...

    12 天前
  • 那些鲜为人知的 TypeScript 功能

    原文地址: medium.com/articode/so… 译文地址:github.com/xiao-T/note… 本文版权归原作者所有,翻译仅用于学习。 过去的几年中,TypeScript ...

    5 个月前
  • 通过简单的示例来理解React Hook

    This hook makes it easy to dynamically change the appearance of your app using CSS variables. You si...

    2 年前
  • 通过示例教你如何打造一个组件库

    2020年大家的flag里有没有造轮子这一项呢?最近终于有空了,打算对组件库下手。 这次重点放在了如何搭建一个组件库上,内容涉及到开源组件库必备的文档、代码规范控制、工程化、编译、单测等各个环节。

    10 个月前
  • 通用 TypeScript 项目结构与实践经验

    据说是 30 万行 TypeScript 项目实践干货?在多年的 TypeScript 项目开发过程中,我们曾多次改变项目结构以适应新增的项目拆分需求,最终形成了现有的通用项目结构。

    3 个月前
  • 进击TypeScript(入门及实战应用)

    前言2020年,越来越多的前端开源项目已经或者正在使用TypeScript重构(ant design、vs code 、vue3等)。正在从事前端开发的我们,已经不能忽视TypeScript整个生态链...

    3 个月前
  • 轱辘UI:基于 Vue 3 + TypeScript 的 UI 组件库

    这是我为了探索 Vue 3 新特性而写的 UI 组件库,请勿用于生产环境。 源代码:github.com/FrankFang/g… 官网:frankfang.gitee.io/gulu-ui-web...

    22 天前
  • 足球特殊指数api接口示例

    分享下足球特殊指数数据,单双、总进球数、半全场赔率api接口示例,详情查看在线文档 接口返回的是Json数据,可以使用fastjson来解析。 package com.huaying.demo.she...

    1 年前

官方社区

扫码加入 JavaScript 社区