-
useState
hook 是一个泛型函数,接收一个类型变量来指定状态的类型
// 指定 name 状态的类型为:string
const [name, setName] = useState<string>('jack');
// 指定 age 状态的类型为:number
const [age, setAge] = useState<number>(28);
-
注意:该类型变量,不仅指定了状态的类型,也指定了 setName 等修改状态函数的参数类型
const [name, setName] = useState<string>('jack');
// 此时,setName 的参数的类型也是 string
setName('rose');
// 错误演示:
// setName(18)
省略类型变量,简化
useState
的调用:
-
在使用 useState 时,只要提供了初始值,TS 就会自动根据初始值来推断出其类型,因此,可以省略类型变量
-
注意:如果 TS 自动推断出来的类型不准确,还得显式指定泛型类型
const [name, setName] = useState('jack');
3. useState 明确指定泛型类型
目标:
能够明确指定
useState
的泛型类型
// 比如,频道列表数据是一个数组,所以,在 JS 中我们将其默认值设置为:[]
// 但是,在 TS 中使用时,如果仅仅将默认值设置为空数组,list 的类型被推断为:never[],此时,无法往数组中添加任何数据
const [list, setList] = useState([]);
-
注意:useState 的初始值是数组、对象等复杂的数据类型,需要明确指定泛型类型
-
因为虽然都是数组、对象,但是,项目开发中不同需求所需要的数组结构、对象结构是不同的。因此,需要明确指定其类型
type Channel = {
id: number;
name: string;
// 明确指定状态的类型,此时,list 的类型为:Channel[]
// Channel[] 表示 Channel 类型的数组,也就是,数组中只能出现 Channel 类型的数据
const [list, setList] = useState<Channel[]>([]);
-
使用 TS 时,应该以类型化思维来写代码,简单来说:
先有类型,再写逻辑代码来使用该类型的数据
-
比如,对于 对象、数组 来说,就应该在使用前先明确指定要用到的对象的类型、数组的类型等等
4. TS 类型-never 类型
目标
:能够知道 TS 中 never 类型的含义
-
never
类型:永远不会出现的值的类型(或永远不会发生的类型)
-
never
类型:处理 TS 类型系统的最底层
-
可以将 never 类型的数据,赋值给任意其他的类型;无法将任何类型(除了 never 类型自己)来分配给 never 类型
let fn = () => {
// 手动通过 throw 抛出一个异常(错误)
throw new Error('err...');
let n = fn(); // n => never
let fn = () => {
while (true) {}
let n = fn(); // n => never
const num = 123;
if (num !== 123) {
let n = num; // n => never
5. useRef 的使用
目标:
能够使用
useRef
配合 TS 操作 DOM
-
useRef
hook 接收一个类型变量,用于指定 current 属性的类型
// 假设操作的是 input 标签,则指定类型为:HTMLInputElement
const inputRef = useRef<HTMLInputElement>(null)
// 此时,把鼠标放在变量 inputRef 上,也可以看到 inputRef.current 属性的类型为: HTMLInputElement | null
// 其中,HTMLInputElement 是我们明确指定的类型,而 null 是参数的类型。因为在创建 ref 对象时,JSX 对应的 DOM 还没有创建,所以,参数默认值先指定为 null
// JSX 中使用 ref:
<input ref={inputRef} />
使用 ref 对象,获取进行 DOM 操作:
-
注意:因为 current 属性的类型是:
HTMLInputElement | null
,所以,必须要从类型中“去掉”
null
才能继续操作
-
可以使用 JS 中的
可选链操作符(?.)
来实现:
-
原理:
?.
会判断 current 属性是否为空值(null 或 undefined),如果不是空值,就继续访问 value 值;如果是空值,不会继续访问 value
-
如果 current 不是空值,其类型为
HTMLInputElement
,就可以拿到 value 值
-
如果 current 是空值,其类型为
null
,不再继续访问 value,代码就不会报错了
const getValue = () => {
// 正确:
console.log(inputRef.current?.value);
// 报错:未处理 current 属性类型为 null 的情况
// console.log(inputRef.current.value)
技巧:在 JSX 中如何获取一个 DOM 对象的类型?鼠标移动到 JSX 元素上,就会显示出来该元素的类型
6. TS 类型-非空断言
目标:能够掌握 TS 中的非空断言的使用
- 如果我们明确的知道对象的属性在使用时一定不为空,那么可以使用 TS 中提供的:非空断言
- 非空断言:
!
,从可能为空的类型中,去掉 null
和 undefined
类型
let x: null | undefined | number;
// t1 的类型为:null | undefined | number
let t1 = x;
// t2 的类型为:number
let t2 = x!;
应用场景:使用 ref 进行 DOM 操作时,可以将 ref 对象的 current 的类型 HTMLInputElement | null
中的 null 类型去掉变为:HTMLInputElemen
const inputRef = useRef<HTMLInputElement>(null);
const getValue = () => {
console.log(inputRef.current!.value);
- 注意:使用非空断言时,一定要确保该属性不为空值,否则,即使类型不报错,将来在代码运行时也会报错!
let x: null | undefined | number = null;
// 错误演示:
// 类型不会报错,但是,代码运行时报错!因为 x 的值为 null
x!.toString();
7. TS 流程控制类型分析
目标:能够通过 if 判断来控制 TS 类型
- TS 文档-流程控制分析
- TS 可以通过 if 判断等操作来通过流程控制分析,来得到更加具体的类型,实现类型收缩(缩小类型的取值范围)
- 这一检查机制也叫做:type guard - 类型守卫
let x: number | string;
if (typeof x === 'number') {
// 鼠标放在 x 上查看类型为: number
console.log(x);
} else {
// 此时,x 的类型为: string
console.log(x);
应用场景:使用 ref 进行 DOM 操作时,通过 if 判断来排除掉 null 类型
const inputRef = useRef<HTMLInputElement>(null);
const getValue = () => {
// 判断 inputRef.current 是否为空,如果是,直接 return 不再执行后面的代码
if (!inputRef.current) return;
// 如果此处代码执行,说明 inputRef.current 不为空,所以,此处可以直接访问 value 属性
console.log(inputRef.current.value);
8. React 路由的使用
目标:能够在 TS 中使用 react 路由
-
安装路由:yarn add react-router-dom@5.3.0
-
安装路由的类型声明文件:yarn add @types/react-router-dom
-
在 pages 目录中,新建组件Home.tsx
和Login.tsx
(注意:组件的后缀为 .tsx
)
-
配置路由规则
核心代码:
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import Login from './pages/Login';
function App() {
return (
<Router>
<div className="App">
<Link to="/home">首页</Link>
<Link to="/login">登录</Link>
<Route path="/home" component={Home}></Route>
<Route path="/login" component={Login}></Route>
</Router>
export default App;
有了 TS 的支持后,代码提示变得非常的精确
9. useHistory 的使用
目标:能够掌握 useHistory 在 TS 中的使用
useHistory
hook 是一个泛型函数,接收一个类型变量来指定额外数据 state 的类型useHistory
hook 用来实现路由之间的跳转。根据跳转时是否携带额外数据,使用方式不同:
1.路由跳转不携带额外数据,用法与 JS 一样:
const history = useHistory();
const login = () => {
history.push('/login');
2.路由跳转时携带额外数据,需要指定泛型类型:
- 注意:泛型类型指定的是额外数据 state 的类型
// 调用 useHistory hook 时,为泛型函数指定额外数据 state 的类型:
const history = useHistory<{ from: string }>();
const login = () => {
history.push('/login', {
from: '/home/article',
// 或者,传入对象参数:
history.push({
pathname: '/login',
state: {
from: '/home/article',
10. useLocation 的使用
目标:能够掌握 useLocation 在 TS 中的使用
1.不获取 state 数据:
const location = useLocation();
2.获取 state 数据:
- 注意:如果跳转路由时没有传递 state,state 的值为 undefined,所以,此处指定类型时也应该考虑到没有传递 state 时的类型
const location = useLocation<{ from: string } | undefined>();
// 因为 state 可能是 undefined 类型,所以,此处通过 ?. 来访问 from
console.log(location.state?.from);
注意:因为 Home 和 Login 都需要指定额外数据 state 的类型,因此可以将类型存放到类型声明文件中,实现类型复用:
// types.d.ts
export type LoginState = { from: string } | undefined;
// Login.tsx 中:
// import type ... 表示:专门用来导入类型的语法
// 此处,使用 import 导入类型时,可以省略 type 也可以带着 type
import type { LoginState } from './types';
const location = useLocation<LoginState>();
// Home.tsx 中:
import type { LoginState } from './types';
const history = useHistory<LoginState>();
11. useParams 的使用
目标:能够掌握 useParams 在 TS 中的使用
useParams
hook 是一个泛型函数,接收一个类型变量来指定 params 对象的类型- 根据配置路由规则时,路由参数是否可选,使用方式不同:
1.路由参数必选
<Route path="/home/publish/:id" />;
// 因为路由规则中要求参数一定存在,所以,此处不需要考虑不存在的情况
const params = useParams<{ id: string }>();
console.log(params.id);
2.路由参数可选
<Route path="/home/publish/:id?" />;
// 因为路由规则中参数是可选的,所以,此处需要考虑 id 不传的情况,让 id 变为可选属性
const params = useParams<{ id?: string }>();
console.log(params.id);
12. TS 类型-unknown 类型
目标:能够知道 TS 中的 unknown 类型
对比 any 和 unknown 类型:
1.对于 any 类型来说,TS 不会对其进行类型检查
// 可以进行任意操作,没有安全可言
let value: any;
value = true;
value = 1;
value.length;
2.unknown 类型
let value: unknown;
value = 'abc'(
// 先转化为具体类型再使用
value as string,
).length;
// 先判断是 string 类型,再使用
if (typeof value === 'string') {
value.length;
12. never 类型和 unknown 类型
- never 处理 TS 类型系统的最底层
- 无法将任意类型的数据赋值给 never 类型
- 可以将 never 类型赋值给任意其他类型
- 理解:never 表示啥也不是,所以,无法给 never 设置任何内容
- 理解:never 处于最底层,相当于任何类型的子类型,所以,可以赋值给其他任何类型
- 比如,'a' 字面量就是 string 的子类型
let s: string = 'a'
- unknown 处于 TS 类型系统的最顶层
- 可以将任意类型的数据赋值给 unknown 类型
- 无法将 unknown 类型赋值给任意其他类型
- 简单来说:unknown 类型可以接受任意类型,但是无法赋值给其他类型
- 理解:unknown 表示不确定,不确定就可以表示任意类型,既然可以是任意类型,所以可以接受任意类型的数据
- 理解:unknown 表示不确定,不确定就可以表示任意类型,既然可以是任意类型,所以就无法赋值给一个特点的类型
// 头部 底部 unknown -> ... -> ...-> never unknown 可以按照 “万物皆对象”
的方式来理解:“万物皆 unknown”
let u: unknown;
// 可以将任意类型的数据赋值给 unknown 类型
u = 1;
u = 'a';
// 错误演示:
// let a: number = u
写在前面:
首先,什么是TypeScript?
官方原话:TypeScript is a typed superset of JavaScript that complies to plain JavaScript. Any host. Any OS. Open source.
TypeScript是JavaScript类型的超集(强类型版本),它可以编译成纯JavaScript,它可以再任何浏览器,任何计算机和任何操作系统上运行,并且开源。
嗯,是的,你可以理解为TypeScript硬是把JavaScript(弱类型语言)"掰弯"了,变成强类型语言;强类语言的优势在于静态类型的检查,TypeScript虽然是强类型的语言,但是如果对象被声明为any类型,
使用TypeScript的主要工作是在组件中定义prop和state的类型。将项目中的.js文件扩展名更改为.ts或.tsx。如果你使用的是create-react-app,它会自动将文件扩展名更改为.tsx。在组件中使用TypeScript。
在交互式监视模式下启动测试运行器。 有关更多信息,请参见关于的部分。
npm run build
构建生产到应用程序build文件夹。 它在生产模式下正确捆绑了React,并优化了构建以获得最佳性能。
生成被最小化,并且文件名包括哈希值。 您的应用已准备好进行部署!
有关更多信息,请参见关于的部分。
npm run eject
注意:这是单向操作。 eject ,您将无法返回!
如果您对构建工具和配置选择不满意,则可以随时eject 。 此命令将从您的项目中删除单个生成依赖项
在交互式监视模式下启动测试运行程序。 有关更多信息,请参见关于的部分。
npm run build
构建生产到应用程序build文件夹。 它在生产模式下正确捆绑了React,并优化了构建以获得最佳性能。
最小化构建,文件名包含哈希。 您的应用已准备好进行部署!
有关更多信息,请参见有关的部分。
npm run eject
注意:这是单向操作。 eject ,您将无法返回!
如果您对构建工具和配置选择不满意,则可以随时eject 。 此命令将从项目中删除单个构建依赖项。
而是将所有配置文件和传递依赖项(webpack,Babel,E
大厂技术高级前端Node进阶点击上方程序员成长指北,关注公众号回复1,加入高级Node交流群工作用的技术栈主要是React hooks + TypeScript。使用三月有余,其...
typescript1、typescript介绍2、特点3、
说起typescript你是不想到了javascript呢,没错,它们确实是有关系的,具体是什么,往下看!
1、typescript介绍
学了这么久的javascript,相信你已经知道了javascript是一门弱类型语言。
强类型语言就是声明变量的同时限制数据类型,而弱类型语言则相反,对于数据类型的限制并不那么严格。
比如你定义了一个变量,但是赋值的时候可以赋任何类型的数据,而强类型就比较严格了,是什么类型就必须严格匹配。
typescrip
转自https://typescript.bootcss.com/tutorials/react.html
这篇快速上手指南会教你如何将TypeScript与React结合起来使用。 在最后,你将学到:
使用TypeScript和React创建工程
使用TSLint进行代码检查
使用Jest和Enzyme进行测试,以及
使用Redux管理状态
我们会使用create-react-app工...
react项目构建可以很简单,但是如果是结合typescript,其实也不是很麻烦,官网也有很明确的说明。有两种办法:
1、直接构建带有typescript的react项目,我们需要增加额外的参数,模版不能使用默认的cra-template。而是使用cra-template-typescript。
npx create-react-app tsreactdemo --template typescript
最早,我们创建typescript的react项目命令好像直接就是np...
本教程不用react-script这种工具,用的webpack + eslint(可选) + prettier(可选) + babel,使用编辑器用的vscode。
以下会涉及到ts语法和redux、react-router-dom的一些技巧,也是入门时学习到的。
depend
# babel
yarn add @babel/core @babel/preset-reac @babel/preset-typescript @babel/preset-env -D
# webpack
泛型是TypeScript中的一个重要部分:它们看起来很奇怪,它们的目的不明显,而且它们可能很难分析。本文旨在帮助你理解和揭开TypeScript泛型的神秘面纱,特别是它们在React中的应用。
Typescript一、关于Typescript1.什么是Typescript?2.安装 TypeScript二、在 react 中使用 ts 需要注意几点三、ts在react中的使用推荐阅读
一、关于Typescript
TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持。
它的第一个版本发布于 2012 年 10 月,经历了多次更新后,现在已成为前端社区中不可忽视的力量,不仅在 Microsoft 内部得到广泛运用,而且 Google 开发的 Angula