React + TypeScript ❤️:优点⚡
我已经开始在React中使用TypeScript了,一段时间后,我开始学习并将它们结合起来实现。我的感受如下:
我的 DX 升级了这么多,简直不敢相信。我会把我最喜欢的几个主要功能分享给大家,希望你会迫不及待地想尝试一下😃!
免责声明⚠️
这不是对 TypeScript 初学者友好的介绍,您至少需要知道如何使用接口,但是,在文章的最后,我将列出我发现非常有用的优秀资源,以及启动和运行 React + TypeScript 并开始黑客攻击的最快方法:
$ npx create-react-app my-app --template typescript
# or
$ yarn create react-app my-app --template typescript
TLDR;
优点:
- 使用类型定义完成代码和类型验证。
- 很棒的社区和学习资源。
缺点:
- TypeScript 语法和泛型等概念可能很难理解。
目录
智能感知
我使用VSCode,它最棒的功能之一是IntelliSense(又称代码自动完成),TypeScript 充分利用了它。
假设我们有一个简单的List
组件,并声明了Props
接口,在本例中是一个 prop labels
,即一个字符串数组:
// List.tsx
import React from 'react';
interface Props {
labels: string[]
}
// We tell TypeScript the parameter type
// + Object destructuring 👇
function List({ labels }: Props): React.Element {
return (
<ul>
{ labels.map((label, index) => {
<li key={index}>{label}</li>
)}
</ul>
);
}
const strings = ['React', 'TypeScript', '❤️'];
<List labels={strings}/>
这是我们得到的:
如果我们labels.
在里面输入List
,我们会得到包含方法和属性的代码补全Array.prototype
,在本例中是Array.prototype.forEach(),然后在callback
函数内部,我们会得到所有方法和属性String.prototype
,在本例中是Array.prototype.toUpperCase()。VSCode
是用 TypeScript 编写的,它内置了原生对象的类型定义,最棒的部分是什么?我们可以声明自己的类型,而且我们使用的大多数库都自带了它们自己的类型定义文件 😃 !
这引出了下一个很棒的功能:
类型定义
React 和 TypeScript 社区非常棒,他们创建了一个庞大的集中式高质量类型定义文件存储库:
DefinitelyTyped / DefinitelyTyped
高质量 TypeScript 类型定义的存储库。
大多数库都将其类型声明文件保存在此 repo 中,有时我们必须独立安装它们,在官方网站上我们可以搜索并找到安装它们的说明,以 React 为例:
$ yarn add @types/react --save-dev
我们如何使用它们?
import React from 'react';
interface Props {
labels: string[]
}
function List({ labels }: Props): React.Element {
const styles: React: React.CSSProperties = {
backgroundColor: 'blue'
}
// ...
}
假设我们要编写一些内联 CSS,在这种情况下,我们可以使用 React 内置的类型定义React.CSSProperties
,如果我们输入了类似的拼写错误,它会显示错误backgroundKolor
,并且我们会获得属性的代码补全😁。
我们还可以看到源代码,以便我们习惯于读写它们。
我们已经学习了如何利用类型定义来实现代码补全,但现在我们将学习它附带的另一个强大功能:
类型验证
如果我们没有传递正确的 prop 类型或者根本没有传递它该怎么办?
interface Props {
labels: string[]
}
function List({ labels }: Props) {
// ...
}
const strings = ['React', 'TypeScript', '❤️'];
const numbers: number[] = [1, 2, 3];
// 1) We pass an array of numbers
<List labels={numbers} />
// 2) We don't pass it
<List />
这些错误信息非常清晰,它们告诉我们 是什么type error
,在哪里declaration
生成的,以及这个 prop 是否真的需要。这些错误信息也适用于函数(尽管 React 组件本身就是函数 😉)。TypeScript
编译器只有在传递正确的参数后才会执行,这在编译代码和检查浏览器之前就能发现潜在的 bug,非常实用。
那么prop-types怎么样?
是的,我们可以使用以下方法实现相同的验证prop-types
:
import React from 'react';
import PropTypes from 'prop-types';
function List({ labels }) {
// ...
}
List.propTypes = {
labels: PropTypes.arrayOf(PropTypes.string).isRequired
}
但是,由于prop-types
在运行时检查我们的代码,我们必须先编译它,在控制台上查看实际错误,而且,这种验证只发生在开发模式下😟,而 TypeScript 会静态分析我们的代码。
钩子
例如,当谈到React HooksuseState
时,TypeScript 非常方便,特别是在类型验证方面。
function Counter() {
// we can also use brackets <> syntax for types declarations:
const [counter, setCounter] = useState<number>(0);
const add = () => {
// this is gonna give us an error 😱
setCounter('string');
}
return(
<div>
<button onClick={add}>+</button>
{counter}
</div>
);
}
通过这种方式,我们确保每次更新时都state
保留值类型,这可以节省我们数小时的调试和麻烦。
不好的部分。🤐 权衡
我们了解了 TypeScript 在编写组件时如何使整个团队受益,假设我们编写了(理想情况下)可重用的组件库,其类型定义明确,而我们的同事导入其中一个,他们会事先看到:
- 道具类型以及是否需要它们。
- 道具名称的代码完成。
这可以节省我们浏览源代码以确保将正确的数据传递给每个组件的时间。
但我们也知道,软件开发中没有银弹。我们选择的每个工具都有其利弊,就 TypeScript 而言,当然有一些:
阅读 TypeScript 可能比较困难:
interface Array<T> {
concat(...items: Array<T[] | T>): T[];
reduce<U>(
callback: (state: U, element: T, index: number, array: T[]) => U,
firstState?: U
): U;
// ···
}
但别担心,我从这篇精彩的文章中得到了这个片段,它解释了每一个细节,那个例子一开始对我来说真的很困惑。
有些概念可能比较复杂,难以理解:
- 接口。
- 泛型。
- 接口与类型。
这些新概念(尤其是在团队成员不熟悉的情况下)可能会带来更多疑问和困惑。
当然,我们可以解决这些问题,这取决于团队成员的经验、可用的时间以及学习新事物的热情。
这篇文章反映了我一段时间以来一直在思考的想法,它很可能成为我下一篇文章的主题everything in Software Development is a trade-off
:
资源
这些是帮助我理解和喜爱 TypeScript 的最佳资源:
-
- 理解 TypeScript 的类型符号
-
typescript-cheatsheets / React
为经验丰富的 React 开发人员提供的 TypeScript 入门速查表
- 面向了解如何构建 Todo 应用的 JS 程序员的 TypeScript 教程
- 为放弃理解泛型的人提供的 TypeScript 泛型
结论
TypeScript 有很多优点和缺点,但我们的实际情况(团队、优先级、目标)决定了我们能否获得更多优势而非劣势,从而让我们的生活更轻松!
在我看来,当涉及到大规模应用程序时,尤其是在构建防弹架构或系统设计时,付出的努力终将获得回报,我们可以编写更少的易出错代码,并更快、更安全地交付功能。
感谢您的阅读,如果您发现这篇文章有用,请在Twitter上关注我并告诉我您的想法!
编码愉快!
文章来源:https://dev.to/diemax/react-typescript-the-good-parts-428f