当前位置: 首页 > 编程日记 > 正文

使用TypeScript映射和条件类型使React组件更出色

by Deepu K Sasidharan

通过Deepu K Sasidharan

使用TypeScript映射和条件类型使React组件更出色 (Make your React components great with TypeScript mapped and conditional types)

You’ve probably heard about TypeScript. You may have heard someone claiming how great type safety is.

您可能听说过TypeScript。 您可能听说过有人声称这种类型的安全性非常好。

TypeScript is great. As someone who hates transpiling his code, I would definitely do it with TypeScript if I had to. So much has been said about TypeScript, and there isn’t really anything new that I can add. But I do believe that type safety is not all about making your code ugly with type definitions everywhere. So how can we write type-safe code without having to litter type declarations everywhere?

TypeScript很棒。 作为讨厌编译他的代码的人,如果需要的话,我一定会使用TypeScript做到这一点。 关于TypeScript的讨论已经很多了,实际上我没有什么可以添加的。 但是我确实相信类型安全并不仅仅在于使代码随处可见都是丑陋的。 那么,我们如何编写类型安全的代码而不必到处乱扔类型声明?

Type inference and advanced features like derived and dynamic types are the answer. Editors and IDEs we use are smart enough to handle code with inferred type gracefully without us having to see the types all the time visually. (Of course, they all usually show you the type when you hover over an inferred type.)

答案就是类型推断和高级功能,例如派生类型和动态类型。 我们使用的编辑器和IDE足够聪明,可以优雅地处理带有推断类型的代码,而无需我们一直在视觉上看到类型。 (当然,当您将鼠标悬停在推断的类型上时,它们通常都会向您显示类型。)

TypeScript has a very good type inference. As a rule of thumb, you can always start without declaring the type for any variable and see if the compiler infers it. With modern editors like VSCode, you can see this immediately. So set your tsconfig to the strict mode. Then start declaring types when the compiler complains.

TypeScript具有非常好的类型推断。 根据经验,您始终可以在不声明任何变量类型的情况下开始,并查看编译器是否推断出它。 使用像VSCode这样的现代编辑器,您可以立即看到这一点。 因此,将tsconfig设置为严格模式。 然后在编译器抱怨时开始声明类型。

Additionally, TypeScript 2.1 and 2.8 introduced a bunch of cool lookup types. Now you can dynamically infer types using different techniques like Intersection types, Union types, Index types, mapped types and conditional types.

此外,TypeScript 2.1和2.8引入了许多很酷的查找类型。 现在,您可以使用不同的技术动态推断类型,例如交集类型,联合类型,索引类型,映射类型和条件类型。

索引类型 (Index types)

Index types enable us to check properties and types of an interface or type dynamically using the keyof T (index type query operator) and T[K](indexed access operator). Let's take the below interface for example.

索引类型使我们能够使用keyof T ( 索引类型查询运算符)T[K] ( 索引访问运算符 )动态检查接口的属性和类型或动态类型 。 让我们以下面的界面为例。

interface Person {name: string;age: number;address: string;sayHi: (msg: string) => string;
}

The keyof T operator gets a union type of all the key names of the type Tand hence keyof Person will give us 'name' | 'age' | 'address' | sayHi' as result.

keyof T操作员搭乘的联合类型的类型的所有键名的T ,因此keyof Person会给我们'name' | 'age' | 'address' | sayHi' 'name' | 'age' | 'address' | sayHi' 'name' | 'age' | 'address' | sayHi'

The T[K] operator gets the type for the provided key. Person['name']will result in string and Person[keyof Person] will result in string | number | ((msg: string) => string).

T[K]运算符获取所提供键的类型。 Person['name']将导致stringPerson[ keyof Person]将导致string | number | ((msg: string) => string) string | number | ((msg: string) => string) string | number | ((msg: string) => string)

映射类型 (Mapped types)

Let us see what mapped types are. Let us say we have the below interface for a Person.

让我们看看什么是映射类型。 假设我们有一个Person的以下界面。

interface Person {name: string;age: number;address: string;sayHi: (msg: string) => string;
}

Now in every project, it is almost always a common requirement to have variations of a certain interface. For example, let’s say we need a read-only version of the person as below.

现在,在每个项目中,拥有特定接口的变体几乎总是一个共同的要求。 例如,假设我们需要如下所示的人员只读版本。

interface ReadonlyPerson {readonly name: string;readonly age: number;readonly address: string;readonly sayHi: (msg: string) => string;
}

In this case, we would have to replicate the Person interface and we have to keep them in sync manually. This is where mapped types will come in handy, so let us use the builtin mapped type, Readonly, for this.

在这种情况下,我们将必须复制Person接口,并且必须手动使其保持同步。 这是映射类型将派上用场的地方,因此让我们使用内置的映射类型Readonly

type ReadonlyPerson  = Readonly<Person>

If you hover over the ReadonlyPerson type you can see the inferred type as below.

如果将鼠标悬停在ReadonlyPerson类型上,则可以看到以下推断的类型。

That is cool, right? Now we can create types from existing types and don’t have to worry about keeping them in sync. How does it work, what does Readonly<Person> do? Let’s take a look at the mapped type.

太酷了吧? 现在,我们可以从现有类型创建类型,而不必担心保持它们同步。 它是如何工作的, Readonly<Person>什么作用? 让我们看一下映射类型。

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

The in operator from TypeScript does the trick here. It maps all the declarations of the existing type into the new type. The keyof operator provides the keys from our type for the mapping. Let us build our own mapped type.

TypeScript的in运算符在这里起到了作用。 它将现有类型的所有声明映射为新类型。 keyof运算符提供了我们类型的映射键。 让我们建立自己的映射类型。

Let us say we need a read-only Person interface where all the fields are nullable as well. We can build a mapped type as below for that.

假设我们需要一个只读的Person接口,其中的所有字段也是可空的。 我们可以为此构建一个映射类型,如下所示。

type ReadonlyNullablePerson = {readonly [P in keyof Person]: Person[P] | null;
}

Let’s make it generic so that it can be used with any interface.

让我们使其通用,以便可以与任何接口一起使用。

type ReadonlyNullable<T> = {readonly [K in keyof T]: T[K] | null;
}type ReadonlyNullablePerson  = ReadonlyNullable<Person>

TypeScript includes Readonly<T>, Partial<T>, Pick<T, K extends keyof T> and Record<K extends string, T> as built-in mapped types. Pick and Record can be used as below, check them in your editor to see what types they produce.

TypeScript包括Readonly<T>Partial<T>Pick<T, K extends keyof T>Record<K extends string, T>作为内置映射类型。 选择和记录可按以下方式使用,请在编辑器中检查它们,以查看它们产生什么类型。

type PersonMinimal = Pick<Person, 'name' | 'age'>type RecordedPerson = Record<'name' | 'address', string>

For every other use case, you can build your own mapped types.

对于其他所有用例,您都可以构建自己的映射类型。

条件类型 (Conditional types)

A conditional type selects one of two possible types based on a condition expressed as a type relationship test.
条件类型根据表示为类型关系测试的条件选择两种可能的类型之一。

Let us look at an example.

让我们来看一个例子。

type Foo<T, U> = T extends U ? string : booleaninterface Me {}
interface You extends Person {}type FooBool = Foo<Me, Person> // will result in boolean
type FooString = Foo<You, Person> // will result in string

The type dynamically inferred from Foo<T, U> will be either string or boolean depending on what the first generic is extended from.

Foo<T, U>动态推断出的类型将是string还是boolean具体取决于第一个泛型的扩展名。

Let us see how we can mix conditional types with mapped types to infer a new type from Person which only includes the non-function properties.

让我们看看如何将条件类型与映射类型混合使用,以从Person推断出仅包含非函数属性的新类型。

type NonFunctionPropNames<T> = {[K in keyof T]: T[K] extends Function ? never : K
}[keyof T];type NonFunctionProps<T> = Pick<T, NonFunctionPropNames<T>>type PersonProps = NonFunctionProps<Person>// Produces the below type
// type PersonProps = {
//     name: string;
//     age: number;
//     address: string;
// }

We first get all the non-function property names from the interface. Then use the Pick mapped type to pick those from the interface to form the new interface.

我们首先从接口获取所有非功能属性名称。 然后使用“ 拾取”映射类型从接口中选择那些类型以形成新接口。

TypeScript provides following inbuilt conditional types:

TypeScript提供以下内置条件类型:

  • Exclude<T, U> – Exclude from T those types that are assignable to U.

    Exclude<T, U> –从T排除可分配给U那些类型。

  • Extract<T, U> – Extract from T those types that are assignable to U.

    Extract<T, U> –从T提取可分配给U那些类型。

  • NonNullable<T> – Exclude null and undefined from T.

    NonNullable<T> –从T排除nullundefined

  • ReturnType<T> – Obtain the return type of a function type.

    ReturnType<T> –获取函数类型的返回类型。

  • InstanceType<T> – Obtain the instance type of a constructor function type.

    InstanceType<T> –获取构造函数类型的实例类型。

让我们使用它 (Let us put it into use)

These advanced types become even more powerful when you combine them together. Let’s see some practical uses of this in React.

当您将它们组合在一起时,这些高级类型将变得更加强大。 让我们看看这在React中的一些实际用法。

ES6中的React组件和Redux Reducer (React component and Redux reducer in ES6)

Let see a simple React component with a reducer written in ES6. Take a look at index.jsx in the below code sandbox:

让我们看一个简单的带有ES6编写的带有reducer的React组件。 在下面的代码沙箱中查看index.jsx

As you can see, we use the prop-types library to define the component props. It is not the most efficient way, as it includes considerable overhead during development. It doesn’t provide full type safety anyway.

如您所见,我们使用prop-types库定义组件prop。 这不是最有效的方法,因为它在开发过程中会包含大量开销。 无论如何,它不提供全类型的安全性。

在TypeScript中使用React组件和Redux reducer (React component and Redux reducer in TypeScript)

Now let us convert this simple example to TypeScript so that it's type safe. Take a look at index.tsx in the below code sandbox:

现在,让我们将这个简单的示例转换为TypeScript,以确保其类型安全。 在下面的代码沙箱中查看index.tsx

As you can see, the code is more type-safe now. It is also much more verbose even without PropTypes library and all the type inference.

如您所见,该代码现在更加类型安全。 即使没有PropTypes库和所有类型推断,它也更加冗长。

使用高级类型在TypeScript中使用React组件和Redux reducer (React component and Redux reducer in TypeScript with advanced types)

Now let us apply the advanced types that we learned to make this example less verbose and even more type safe. Take a look at index.tsx in the below code sandbox:

现在,让我们应用我们学到的高级类型,使该示例不再冗长,甚至更加安全。 在下面的代码沙箱中查看index.tsx

As you can see, we used Readonly and ReturnType mapping along with some other type inference techniques to write a more type-safe but less verbose version of the component.

如您所见,我们使用ReadonlyReturnType映射以及其他一些类型推断技术来编写类型更安全但不那么冗长的组件版本。

结论 (Conclusion)

If you are using React with TypeScript, then these are some of the techniques you must apply. If you are considering a type system for React, then look no further than TypeScript. It has great features, great tooling, excellent IDE/Editor support and an awesome community.

如果您将React与TypeScript一起使用,那么这些是您必须应用的一些技术。 如果您正在考虑使用React的类型系统,那么TypeScript就是您的最佳选择。 它具有强大的功能,强大的工具,出色的IDE /编辑器支持以及强大的社区。

I gave a talk on TypeScript for Devoxx 2018, and you can see the video and slides if you like here.

我在Devoxx 2018的TypeScript上进行了演讲,如果您愿意的话可以观看视频和幻灯片。

Check out my book “Full Stack Development with JHipster” on Amazon and Packt if you like to learn about Full stack development with an awesome stack.

如果您想了解有关使用超赞堆栈进行全栈开发的知识,请查看我在Amazon和Packt上撰写的使用JHipster进行全栈开发 ”一书。

If you like JHipster don’t forget to give it a star on Github.

如果您喜欢JHipster,请不要忘记在Github上给它加个星。

If you like this article, please leave some claps (Did you know that you can clap multiple times? ? )

如果您喜欢本文,请留下一些鼓掌(您知道您可以多次鼓掌吗??)

You can follow me on Twitter and LinkedIn.

您可以在Twitter和LinkedIn上关注我。

翻译自: https://www.freecodecamp.org/news/make-react-components-great-again-with-typescript-mapped-and-conditional-types-fa729bfc1a79/

相关文章:

2017年6月16号课堂笔记

2017年6月16号 星期五 空气质量&#xff1a;中度污染~轻度污染 内容&#xff1a;jQuery&#xff1a;remove&#xff0c;bind&#xff0c;attr&#xff0c;on和live&#xff0c;同辈和父辈节点的操作&#xff0c; keyup/keypress/keydown,focus-blur应用&#xff0c;表单事件/键…

大宗商品(Bulk Stock)交易

大宗商品&#xff08;Bulk Stock&#xff09;是指可进入流通领域&#xff0c;但非零售环节&#xff0c;具有商品属性用于工农业生产与消费使用的大批量买卖的物质商品。在金融投资市场&#xff0c;大宗商品指同质化. 可交易. 被广泛作为工业基础原材料的商品大宗商品电子交易主…

【Ant Design Pro 二】 创建页面,组件,并在页面调用

开发交流qq群 173683895 路由里面的参数作用介绍: {path: "/a_nowdayserver/nowdayserver", //随便取名,显示在访问路径url中,如果是子路由,需要和父路径匹配icon: "file", //菜单栏显示的图标name: "你好", //菜单栏显示的标题component…

安卓收取费用_作为自由职业者应收取的费用:以价值为基础的定价是否能达到炒作的目的?...

安卓收取费用by Benek Lisefski由Benek Lisefski 作为自由职业者应收取的费用&#xff1a;以价值为基础的定价是否能达到炒作的目的&#xff1f; (What to charge as a freelancer: does value-based pricing live up to the hype?) 定价很难。 (Pricing is hard.) Even afte…

Java笔记(25):设计模式概述

1、设计模式的概述和分类 设计模式&#xff1a; 经验的总结。 A:创建型 创建对象 B:结构型 对象的组成 C:行为型 对象的功能创建型模式&#xff1a;1)简单工厂模式 2)工厂方法模式 3)设计模式 2、简单工厂模式概述和使用 1 package cn.itcast_01; 2 3 public abstract class A…

Ant Design Pro 使用图表 charts bizcharts

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 淌了一下午坑,都是辛酸泪 总结:首先要知道, 它不能直接使用 charts ,需要安装 bizcharts 插件,然后导入 bizcharts 中的 charts; 点击跳转到 bizcharts 官方文档,建议看完整个流程再跳转 首先,…

【剑指offer 面试题47】不用加减乘除做加法

思路&#xff1a; 利用位运算 C&#xff1a; 1 #include <iostream>2 using namespace std;3 4 int main()5 {6 int a 11, b 17;7 int sum, carry;8 do9 { 10 sum a ^ b; 11 carry (a & b) << 1; 12 a sum; 13 …

travis-ci自动部署_如何使用Travis CI部署(几乎)零恐惧的Cloud Foundry应用

travis-ci自动部署by Robin Bobbitt罗宾波比(Robin Bobbitt) 如何使用Travis CI部署(几乎)零恐惧的Cloud Foundry应用 (How to deploy your Cloud Foundry app with (almost) zero fear using Travis CI) Application deployments to the cloud should be painless. We should…

Activiti 规则任务(businessRuleTask)

Activiti 规则任务&#xff08;businessRuleTask&#xff09; 作者&#xff1a;邓家海 目前国内研究Activiti规则任务businessRuleTask&#xff09;的文章在网上应该不超出3篇 小觑夜漫酒作伴&#xff0c;破晓黎明当笑言 前言&#xff1a; 最近一直在研究Activiti工作流的自动化…

10年工作经验老程序员推荐的7个开发类工具

做.NET软件工作已经10年了&#xff0c;从程序员做到高级程序员&#xff0c;再到技术主管&#xff0c;技术总监。见证了Visual Studio .NET 2003,Visul Studio 2005, Visual Studio Team System 2008, Visual Studio 2010 Ultimate,Visual Studio 2013一系列近5个版本的变化与亲…

PHP SSL certificate: unable to get local issuer certificate的解决办法

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 当本地curl需要访问https时&#xff0c;出现SSL certificate: unable to get local issuer certificate错误信息 解决办法&#xff1a; 到http://curl.haxx.se/ca/cacert.pem下载pem文件&#xff0c;并…

辞职前为什么挣扎_当您感到自己像开发人员一样挣扎时,为什么学得最多

辞职前为什么挣扎by Walt Schlender由Walt Schlender 当您感到自己像开发人员一样挣扎时&#xff0c;为什么学得最多 (Why you learn the most when you feel like you’re struggling as a developer) The times when I have made the greatest leaps in my development skil…

Hadoop学习之Mapreduce执行过程详解

一、MapReduce执行过程 MapReduce运行时&#xff0c;首先通过Map读取HDFS中的数据&#xff0c;然后经过拆分&#xff0c;将每个文件中的每行数据分拆成键值对&#xff0c;最后输出作为Reduce的输入&#xff0c;大体执行流程如下图所示&#xff1a; 整个流程图具体来说&#xff…

汇编试验十五:安装新的int 9中断例程

安装新的int 9中断例程&#xff08;按A键后显示满屏幕的A&#xff09; int 9 是外中断&#xff0c;同样&#xff0c;程序编写还是和其他中断例程类似&#xff0c;安装&#xff08;复制&#xff09;&#xff0c;调用&#xff1b; 不同点是在于&#xff0c;他要从端口读取数据60h…

php判断前端传的多个字段与数据库匹配

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 代码 <?phpheader("Content-Type:text/html;charsetutf8"); header("Access-Control-Allow-Origin: *"); //解决跨域header(Access-Control-Allow-Methods:POST);// 响应类型 …

javascript编写_用JavaScript深入探讨:为什么对编写好的代码至关重要。

javascript编写Using simple terminology and a real world example, this post explains what this is and why it is useful.这篇文章使用简单的术语和一个真实的例子&#xff0c;解释了this是什么以及为什么有用。 这是给你的吗 (Is this for you) I have noticed that man…

peak num

class Solution {public: int findPeakElement(vector<int>& nums) { int i0; int nnums.size(); while(i<n){ if(i0){ //处理第一位 if(nums[1] < nums[0]) return 0; else { …

用Eclipse的snippets功能实现代码重用

snippets功能实现代码重用 Snippets 代码片段是Eclipse的一个插件。 很多时候可以通过这个功能&#xff0c;重复使用常用的代码片段&#xff0c;加快开发效率。 创建一个代码段的步骤&#xff1a; 在Eclipse的editor中选中一块代码段&#xff0c;右键点击【Add to Snippets…

JS删除选中的数组

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 js // 删除数组deleteArr: function (e) {let middlearr [{a:1},{b:2}];//全部数组let items [{a:1}];//选中的数组for (var i 0; i < items.length; i) {for (var j 0; j < middlearr.lengt…

Git合并和变基简介:它们是什么,以及如何使用它们

by Vali Shah通过瓦利沙阿 Git合并和Git变基简介&#xff1a;它们做什么以及何时使用它们 (An Introduction to Git Merge and Git Rebase: What They Do and When to Use Them) As a Developer, many of us have to choose between Merge and Rebase. With all the reference…

[转]单点登录原理与简单实现

一、单系统登录机制 1、http无状态协议 web应用采用browser/server架构&#xff0c;http作为通信协议。http是无状态协议&#xff0c;浏览器的每一次请求&#xff0c;服务器会独立处理&#xff0c;不与之前或之后的请求产生关联&#xff0c;这个过程用下图说明&#xff0c;三次…

[JAVA] DUMP

jmap -dump:live,formatb,fileD:\heap.bin 31563156是PID转载于:https://www.cnblogs.com/MasterMonkInTemple/p/4655547.html

ThinkPHP 5.0 入门教程 一:安装ThinkPHP并在Web浏览器访问

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 严格来说&#xff0c;ThinkPHP无需安装过程&#xff0c;这里所说的安装其实就是把ThinkPHP框架放入WEB运行环境&#xff08;前提是你的WEB运行环境已经OK&#xff09; 下面我们开始安装ThinkPHP的运行环…

以太坊区块链同步_以太坊69:如何在10分钟内建立完全同步的区块链节点

以太坊区块链同步by Lukas Lukac卢卡斯卢卡奇(Lukas Lukac) Ethereu M 69&#xff1a;如何在10分钟内建立完全同步的区块链节点 (Ethereum 69: how to set up a fully synced blockchain node in 10 mins) Welcome in the first article of our new go-ethereum series!欢迎来…

微信小程序客服实现自动回复图文消息链接,点击去关注公众号

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 用户打开客服消息&#xff0c;发送任意消息自动回复图文链接&#xff0c;达到关注公众号的目的。 先看效果&#xff1a; 打开芝麻小客服的后台&#xff0c;选择一键接入小程序智能客服 点击跳转 1.授权…

HtmlUnit、httpclient、jsoup爬取网页信息并解析

转载&#xff1a;http://tianxingzhe.blog.51cto.com/3390077/1755511转载于:https://www.cnblogs.com/puhongtao/p/7063563.html

《Maven 实战》笔记之setting.xml介绍

maven是什么&#xff1f;有什么用&#xff1f; Maven是一个跨平台的项目管理工具,主要服务于Java平台的项目构建,依赖管理和项目信息管理。项目构建包括创建项目框架、清理、编译、测试、到生成报告&#xff0c;再到打包和部署&#xff0c;项目信息包括项目描述,开发者列表,版本…

框架依赖注入和普通依赖注入_依赖注入快速入门:它是什么,以及何时使用它...

框架依赖注入和普通依赖注入by Bhavya Karia通过Bhavya Karia 介绍 (Introduction) In software engineering, dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that ca…

微信小程序自定义弹出框组件,模拟wx.showModal

微信小程序开发交流qq群 173683895 效果图&#xff1a; 代码 wxml <view wx:if{{showModal}}><view classmask_layer bindtapmodal_click_Hidden /><view classmodal_box><view class"title">取消订单</view><view classconte…

IOS tableView删除数据

NSMutableArray *_allshops; NSMutableArray *_deleteshops; -(IBAction)remove{ 1. //记录删除的行号 //创建动态数组存放行号的集合 NSMutableArray *deletepath [NSMutableArray array]; //遍历存放删除数据的数组&#xff0c;把行号放到deletepath中 for (Shop * s in _de…