React 中的TypeScript开发范式

在 TypeScript 中使用 React 可以提高代码的可维护性、可读性和可靠性。TypeScript 提供了静态类型检查和丰富的类型系统,这些功能在 React 开发中非常有用。下面详细介绍如何在 React 项目中使用 TypeScript,并结合泛型和 infer 来定义类型。

1. 项目初始化

首先,创建一个使用 TypeScript 的 React 项目:

pnpm create vite my-app --template react-ts
cd my-app

2. 基本用法

在 TypeScript 中,可以为组件的 props 和 state 定义类型。

函数组件:

import React from 'react';
interface GreetingProps {name: string;
}const Greeting: React.FC<GreetingProps> = (( name )) => {return <h1>Hello, {name}!</h1>;
};export default Greeting;

类组件:

import React, { Component } from 'react';interface CounterProps {initialCount?: number;
}interface CounterState {count: number;
}class Counter extends Component<CounterProps, CounterState> {static defaultProps = {initialCount: 0,};constructor(props: CounterProps) {super(props);this.state = { count: props.initialCount || 0 };render() {return (<div><p>Count: {this.state.count}</p><button onClick={() => this.setState({count: this.state.count + 1})}>Increment</button></div>);}}
}export default Counter;

3. 使用泛型

泛型允许我们定义可以在多种类型之间复用的组件和函数。

要想定义出灵活的组件类型,泛型和 infer 的使用必不可少,如果你在 React 开发过程中大量用到 any ,说明你你没有真正掌握 Typescript,因为只要你灵活掌握了 Typescript,那么在项目中所有的类型均能通过类型定义来推导约束。

示例:泛型列表组件

import React from 'react';interface ListProps<T> {items: T[];renderItem: (item: T) => React.ReactNode;
}function List<T>({ items, renderItem }: ListProps<T>) {return (<ul>{items.map((item, index) => (<li key={index}>{renderItem(item)}</li>))}</ul>);
}// 使用泛型列表组件
const NumberList = () => {const numbers = [1, 2, 3, 4, 5];return <List items={numbers} renderItem={(num) => <span>{num}</span>} />;
};const StringList = () => {const strings = ['one', 'two', 'three'];return <List items={strings} renderItem={(str) => <strong>{str}</strong>} />;
};export { NumberList, StringList };

4. 使用 infer 定义类型

infer 关键字可以在条件类型中使用,用于推断类型。

示例:推断函数返回类型

type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;function getUser() {return { name: 'John', age: 30 };
}type User = GetReturnType<typeof getUser>; // { name: string; age: number; }

示例:推断组件 props 类型

import React, { ComponentType } from 'react';type InferProps<T> = T extends ComponentType<infer P> ? P : never;const MyComponent = (props: { name: string; age: number }) => {return <div>{props.name} is {props.age} years old.</div>;
};type MyComponentProps = InferProps<typeof MyComponent>; // { name: string; age: number }

5. 综合示例

综合示例:使用 TypeScript、泛型和 infer 定义类型并在 React 组件中使用。

import React from 'react';// 定义一个数据类型
interface User {id: number;name: string;
}// 定义一个泛型函数组件,接收数据和渲染函数作为参数
interface DataListProps<T> {data: T[];renderItem: (item: T) => React.ReactNode;
}const DataList = <T,>({ data, renderItem }: DataListProps<T>) => {return (<ul>{data.map((item) => (<li key={(item as any).id}>{renderItem(item)}</li>))}</ul>);
};// 使用 infer 推断组件 props 类型
type InferProps<T> = T extends React.ComponentType<infer P> ? P : never;// 创建一个渲染 user 数据的组件
const UserList: React.FC<DataListProps<User>> = (props) => {return <DataList {...props} />;
};// 使用 UserList 组件
const App: React.FC = () => {const users: User[] = [{ id: 1, name: 'John' },{ id: 2, name: 'Jane' },];return (<div><h1>User List</h1><UserList data={users} renderItem={(user) => <span>{user.name}</span>} /></div>);
};export default App;

在这个综合示例中:

1. 定义了一个 User 类型;

2. 创建了一个泛型组件 Datalist,用于渲染任意类型的数据列表;

3. 使用 infer 推断 UserList 组件的 props 类型;

4. 在 App 组件中使用 UserList 组件渲染用户数据列表;

6. 针对 React 的进阶版 tsconfig

tsconfig.json 是 TypeScript 项目配置的重要文件,通过合理配置,可以提高开发效率和代码质量。

针对 React 项目,重点配置项包括目标版本、库、模块解析、JSX 支持以及严格类型检查选项。

根据项目需求,可以进一步调整和扩展配置,确保最佳的开发体验。

这是一个基础的 tsconfig.json 示例,适用于大多数 React 项目:

{"compilerOptions": {"target": "es2017", // 指定 ECMAScript 目标版本。ES5 兼容性最好,可以在大多数浏览器中运行"lib": ["dom", "dom.iterable", "esnext"], // 指定编译时包含的库文件。通常包括 dom、dom.iterable和esnext"allowJs": true, // 允许编译 .js 文件。适用于项目中混合使用 TypeScript 和 JavaScript 文件"skipLibCheck": true, // 跳过类型声明文件的类型检查。可以加快编译速度"esModuleInterop": true, // 允许对 ES 模块默认导入进行编译时的兼容处理"allowSyntheticDefaultImports": true, // 允许从没有默认导出的模块中默认导入。与 esModuleInterop 配合使用"strict": true, // 启用所有严格类型检查选项。建议开启以确保类型安全"forceConsistentCasingInFileNames": true, // 禁止文件名大小写不一致。保证跨平台一致性"module": "esnext", // 指定模块代码生成方式。esnext 适用于现代 JavaScript 运行环境"moduleResolution": "node", // 指定模块解析策略。node 适用于 Node.js 生态系统"resolveJsonModule": true, // 允许导入 JSON 文件"isolatedModules": true, // 将每个文件作为独立的模块。对 Babel 等工具很有用"noEmit": true, // 禁止生成输出文件。适用于仅进行类型检查的项目"jsx": "react-jsx", // 指定 JSX 代码生成方式。React 17 及以上版本推荐使用 react-jsx"baseUrl": "./src", // 配置基地址,使导入模块时更简洁"paths": { // 配置路径别名,使导入模块时更简洁"@components/*": ["components/*"],"@utils/*": ["utils/*"]},"strictNullChecks": true, // 启用严格的 null 检查"noImplicitAny": true, // 禁止隐式的 any 类型"noImplicitThis": true, // 禁止隐式的 this 类型"alwaysStrict": true, // 如终以严格模式"noUnusedLocals": true, // 报告未使用的局部变量"noUnusedParameters": true, // 报告未使用的函数参数"noImplicitReturns": true, // 所有代码路径必须显式返回值"noFallthroughCasesInSwitch": true // 禁止 switch 语句中的 case 语句贯穿},"include": ["src"], // 指定要包含的文件和目录。通常指定src 目录"exclude": ["node_modules", "build"] // 排除指定的目录
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/83196.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

72道Nginx高频题整理(附答案背诵版)

1. 简述什么是Nginx &#xff1f; Nginx 是一个开源的高性能HTTP和反向代理服务器&#xff0c;也能够用作IMAP/POP3/SMTP代理服务器。它最初由Igor Sysoev为俄罗斯的一个大型网站Rambler开发&#xff0c;并在2004年首次公开发布。Nginx被设计用来解决C10k问题&#xff0c;即同…

AI时代,数据分析师如何成为不可替代的个体

在数据爆炸的 AI 时代&#xff0c;AI工具正以惊人的速度重塑数据分析行业&#xff0c;数据分析师的工作方式正在经历一场前所未有的变革。数据分析师又该如何破局&#xff0c;让自己不被AI取代呢&#xff1f; 一、AI工具对重复性工作的彻底解构 如以往我们需要花几天写一份数…

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…

Kafka入门-Broker以及文件存储机制

Kafka Broker Broker实际上就是kafka实例&#xff0c;每一个节点都是独立的Kafka服务器。 Zookeeper中存储的Kafka信息 节点的服役以及退役 服役 首先要重新建立一台全新的服务器105&#xff0c;并且在服务器中安装JDK、Zookeeper、以及Kafka。配置好基础的信息之后&#x…

dexcap升级版之DexWild——面向户外环境的灵巧手交互策略:人类和机器人演示协同训练(人类直接带上动捕手套采集数据)

前言 截止到25年6.6日&#xff0c;在没动我司『七月在线』南京、武汉团队的机器的前提下&#xff0c;长沙这边所需的前几个开发设备都已到齐——机械臂、宇树g1 edu、VR、吊架 ​长沙团队必须尽快追上南京步伐 加速前进 如上篇文章所说的&#xff0c; 为尽快 让近期新招的新同…

【基于阿里云搭建数据仓库(离线)】使用UDTF时出现报错“FlatEventUDTF cannot be resolved”

目录 问题&#xff1a; 可能的原因有&#xff1a; 解决方法&#xff1a; 问题&#xff1a; 已经将包含第三方依赖的jar包上传到dataworks&#xff0c;并且成功注册函数&#xff0c;但是还是报错&#xff1a;“FlatEventUDTF cannot be resolved”&#xff0c;如下&#xff1a…

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +

【LC实战派】小智固件编译

这篇写给立创吴总&#xff0c;是节前答应他配合git代码的说明&#xff1b;也给所有对小智感兴趣的小伙伴。 请多提意见&#xff0c;让这份文档更有价值 - 第一当然是拉取源码 - git clone https://github.com/78/xiaozhi-esp32.git 完成后&#xff0c;先查看固件中实际的…

有没有 MariaDB 5.5.56 对应 MySQL CONNECTION_CONTROL 插件

有没有 MariaDB 对应 MySQL CONNECTION_CONTROL 插件 背景 写这篇文章的目的是因为昨晚半夜突然被call起来&#xff0c;有一套系统的mysql数据库启动失败了。尝试了重启服务器也不行。让我协助排查一下问题出在哪。 分析过程 一开始拿到服务器IP地址&#xff0c;就去数据库…

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…

LLMs 系列科普文(11)

目前我们已经介绍了大语言模型训练的两个主要阶段。第一阶段被称为预训练阶段&#xff0c;主要是基于互联网文档进行训练。当你用互联网文档训练一个语言模型时&#xff0c;得到的就是所谓的 base 模型&#xff0c;它本质上就是一个互联网文档模拟器&#xff0c;我们发现这是个…

深度学习环境配置指南:基于Anaconda与PyCharm的全流程操作

一、环境搭建前的准备 1. 查看基础环境位置 conda env list 操作说明&#xff1a;通过该命令确认Anaconda默认环境&#xff08;base&#xff09;所在磁盘路径&#xff08;如D盘&#xff09;&#xff0c;后续操作需跳转至该磁盘根目录。 二、创建与激活独立虚拟环境 1. 创…

【2D与3D SLAM中的扫描匹配算法全面解析】

引言 扫描匹配(Scan Matching)是同步定位与地图构建(SLAM)系统中的核心组件&#xff0c;它通过对齐连续的传感器观测数据来估计机器人的运动。本文将深入探讨2D和3D SLAM中的各种扫描匹配算法&#xff0c;包括数学原理、实现细节以及实际应用中的性能对比&#xff0c;特别关注…

力扣160.相交链表

题目描述 难度&#xff1a;简单 示例 思路 使用双指针 使用指针分别指向两个不同的链表进行比较 解题方法 1.首先进行非空判断 2.初始化指针分别指向两个链表 3.遍历链表 while (pA ! pB)&#xff1a; 当pA和pB不相等时&#xff0c;继续循环。如果pA和pB相等&#xff0c;说明找…

本地项目push到git

cd /home/user/project git init 添加远程仓库地址 git remote add origin https://github.com/user/repo.git 创建并切换到新分支 git checkout -b swift 添加文件到暂存区 git add . git commit -m “swift训练评测” git push -u origin swift —force #首次 git push …

uni-app学习笔记二十九--数据缓存

uni.setStorageSync(KEY,DATA) 将 data 存储在本地缓存中指定的 key 中&#xff0c;如果有多个key相同&#xff0c;下面的会覆盖掉原上面的该 key 对应的内容&#xff0c;这是一个同步接口。数据可以是字符串&#xff0c;可以是数组。 <script setup>uni.setStorageSyn…

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…

NFC碰碰卡发视频源码搭建与写卡功能开发实践

在信息快速传播的时代&#xff0c;便捷的数据交互方式成为用户的迫切需求。“碰一碰发视频” 结合写卡功能&#xff0c;为视频分享提供了新颖高效的解决方案&#xff0c;在社交娱乐、商业推广等场景中展现出巨大潜力。本文将详细介绍碰一碰发视频源码搭建以及写卡功能开发的全过…