Props 与 State 类型定义

下面,我们来系统的梳理关于 TypeScript 集成:Props 与 State 类型定义 的基本知识点:


一、TypeScript 在 React 中的核心价值

TypeScript 为 React 开发提供了强大的类型安全保证,特别是在定义组件 Props 和 State 时:

  • 类型安全:编译时捕获类型错误
  • 代码智能提示:增强开发体验
  • 文档化:类型即文档
  • 重构友好:减少破坏性变更
  • 协作效率:明确接口约定

二、基础类型定义

2.1 Props 类型定义

函数组件
interface UserCardProps {name: string;age: number;isAdmin?: boolean; // 可选属性onSelect: (userId: number) => void; // 函数属性
}const UserCard: React.FC<UserCardProps> = ({ name, age,isAdmin = false, // 默认值onSelect 
}) => {return (<div onClick={() => onSelect(1)}><h2>{name}</h2><p>Age: {age}</p>{isAdmin && <span>Admin</span>}</div>);
};
类组件
interface CounterProps {initialCount: number;max?: number;
}interface CounterState {count: number;
}class Counter extends React.Component<CounterProps, CounterState> {state: CounterState = {count: this.props.initialCount};increment = () => {this.setState(prev => ({count: prev.count + 1}));};render() {return (<div><p>Count: {this.state.count}</p><button onClick={this.increment}>Increment</button></div>);}
}

2.2 State 类型定义

useState Hook
interface UserState {id: number;name: string;email: string;isLoading: boolean;
}const UserProfile: React.FC = () => {const [user, setUser] = React.useState<UserState | null>(null);// 初始化状态const [isLoading, setIsLoading] = React.useState<boolean>(true);// 更新状态const updateEmail = (newEmail: string) => {setUser(prev => prev ? {...prev, email: newEmail} : null);};return (<div>{user ? (<div><h1>{user.name}</h1><p>Email: {user.email}</p></div>) : (<p>Loading user...</p>)}</div>);
};

三、复杂类型定义

3.1 联合类型

type Status = 'idle' | 'loading' | 'success' | 'error';interface ApiState<T> {data: T | null;status: Status;error: string | null;
}const useApi = <T,>(url: string): ApiState<T> => {const [state, setState] = React.useState<ApiState<T>>({data: null,status: 'idle',error: null});React.useEffect(() => {const fetchData = async () => {setState(prev => ({...prev, status: 'loading'}));try {const response = await fetch(url);const data = await response.json() as T;setState({data, status: 'success', error: null});} catch (error) {setState({data: null,status: 'error',error: error instanceof Error ? error.message : 'Unknown error'});}};fetchData();}, [url]);return state;
};

3.2 类型别名 vs 接口

特性类型别名 (type)接口 (interface)
声明合并
扩展&extends
实现
联合类型
元组
基本类型

推荐用法

  • 对象类型:优先使用接口
  • 联合类型/元组:使用类型别名
  • 复杂类型组合:结合使用

3.3 泛型组件

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>);
}// 使用
interface User {id: number;name: string;
}const UserList: React.FC = () => {const users: User[] = [{ id: 1, name: 'Alice' },{ id: 2, name: 'Bob' }];return (<Listitems={users}renderItem={(user) => <span>{user.name}</span>}/>);
};

四、高级类型技巧

4.1 实用工具类型

// Partial: 所有属性变为可选
type PartialUser = Partial<User>;// Readonly: 所有属性变为只读
type ReadonlyUser = Readonly<User>;// Pick: 选择部分属性
type UserPreview = Pick<User, 'id' | 'name'>;// Omit: 排除部分属性
type UserWithoutId = Omit<User, 'id'>;// Record: 键值对类型
type StatusColors = Record<Status, string>;// ReturnType: 获取函数返回类型
type ApiResponse = ReturnType<typeof fetchUser>;// 在组件中使用
interface UserFormProps {initialValues: Partial<User>;onSubmit: (values: Omit<User, 'id'>) => void;
}

4.2 类型守卫

interface Admin {role: 'admin';permissions: string[];
}interface RegularUser {role: 'user';isPremium: boolean;
}type UserType = Admin | RegularUser;function UserProfile({ user }: { user: UserType }) {// 类型守卫if (user.role === 'admin') {return (<div><h2>Admin Panel</h2><p>Permissions: {user.permissions.join(', ')}</p></div>);}return (<div><h2>User Profile</h2><p>Premium: {user.isPremium ? 'Yes' : 'No'}</p></div>);
}

4.3 类型继承与组合

interface BaseProps {className?: string;style?: React.CSSProperties;
}interface UserCardProps extends BaseProps {user: User;onSelect: (userId: number) => void;
}// 组合类型
type ModalProps = BaseProps & {isOpen: boolean;onClose: () => void;title: string;
};

五、状态管理类型

5.1 useState 高级用法

// 复杂对象类型
type FormState = {values: {username: string;email: string;};errors: {username?: string;email?: string;};isSubmitting: boolean;
};const [formState, setFormState] = useState<FormState>({values: { username: '', email: '' },errors: {},isSubmitting: false
});// 函数式更新
setFormState(prev => ({...prev,values: {...prev.values,username: 'newUsername'}
}));

5.2 useReducer 类型定义

type CounterAction =| { type: 'increment' }| { type: 'decrement' }| { type: 'reset'; payload: number };interface CounterState {count: number;
}function counterReducer(state: CounterState, action: CounterAction): CounterState {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };case 'reset':return { count: action.payload };default:return state;}
}const Counter: React.FC = () => {const [state, dispatch] = useReducer(counterReducer, { count: 0 });return (<div><p>Count: {state.count}</p><button onClick={() => dispatch({ type: 'increment' })}>+</button><button onClick={() => dispatch({ type: 'decrement' })}>-</button><button onClick={() => dispatch({ type: 'reset', payload: 0 })}>Reset</button></div>);
};

5.3 Context 类型

interface Theme {primary: string;secondary: string;text: string;
}interface ThemeContextProps {theme: Theme;toggleTheme: () => void;isDarkMode: boolean;
}// 创建带默认值的Context
const ThemeContext = React.createContext<ThemeContextProps>({theme: {primary: '#3498db',secondary: '#2ecc71',text: '#333'},toggleTheme: () => {},isDarkMode: false
});// Provider组件
const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {const [isDarkMode, setIsDarkMode] = useState(false);const theme: Theme = isDarkMode ? { primary: '#2980b9', secondary: '#27ae60', text: '#fff' } :{ primary: '#3498db', secondary: '#2ecc71', text: '#333' };const toggleTheme = () => setIsDarkMode(!isDarkMode);return (<ThemeContext.Provider value={{ theme, toggleTheme, isDarkMode }}>{children}</ThemeContext.Provider>);
};// 自定义Hook
export const useTheme = () => {const context = useContext(ThemeContext);if (!context) {throw new Error('useTheme must be used within a ThemeProvider');}return context;
};

六、事件处理类型

6.1 常用事件类型

const InputComponent: React.FC = () => {// 输入事件const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {console.log(e.target.value);};// 表单提交const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {e.preventDefault();// 处理表单逻辑};// 鼠标事件const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {console.log('Clicked at:', e.clientX, e.clientY);};// 键盘事件const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {if (e.key === 'Enter') {console.log('Enter pressed');}};return (<form onSubmit={handleSubmit}><input type="text" onChange={handleChange} onKeyDown={handleKeyDown}/><button type="submit" onClick={handleClick}>Submit</button></form>);
};

6.2 自定义事件类型

interface CustomModalProps {isOpen: boolean;onClose: () => void;onConfirm: (result: boolean) => void;
}const CustomModal: React.FC<CustomModalProps> = ({ isOpen, onClose, onConfirm 
}) => {if (!isOpen) return null;return (<div className="modal"><div className="modal-content"><p>Are you sure?</p><button onClick={() => onConfirm(true)}>Yes</button><button onClick={() => onConfirm(false)}>No</button><button onClick={onClose}>Cancel</button></div></div>);
};

七、默认 Props 处理

7.1 函数组件默认 Props

interface ButtonProps {variant?: 'primary' | 'secondary' | 'outline';size?: 'small' | 'medium' | 'large';children: React.ReactNode;onClick?: () => void;
}const Button: React.FC<ButtonProps> = ({ variant = 'primary', size = 'medium',children,onClick 
}) => {return (<button className={`btn btn-${variant} btn-${size}`}onClick={onClick}>{children}</button>);
};Button.defaultProps = {variant: 'primary',size: 'medium'
};

7.2 默认 Props 与 TypeScript

// 更好的方式:使用默认参数值
const Button = ({variant = 'primary' as const, // 确保类型正确size = 'medium' as const,children,onClick
}: ButtonProps) => {// ...
};// 处理需要计算的默认值
const getDefaultSize = () => 'medium' as const;const Button = ({variant = 'primary' as const,size = getDefaultSize(),children,onClick
}: ButtonProps) => {// ...
};

八、实践与问题

8.1 类型定义最佳实践

  1. 单一职责原则

    • 保持接口小巧专注
    • 组合而非继承
  2. 命名约定

    • 组件 Props:ComponentNameProps
    • 状态类型:ComponentNameState
    • 事件处理函数:handleEventName
  3. 类型复用

    • 提取通用类型到单独文件
    • 使用 export 导出类型
  4. 类型安全

    • 避免使用 any
    • 谨慎使用类型断言 as

8.2 常见问题解决方案

问题1:可选属性与默认值冲突

interface Props {color?: 'red' | 'blue';
}// 解决方案:提供默认值
const Component = ({ color = 'red' }: Props) => { /* ... */ };

问题2:动态组件 Props

// 使用 React.ComponentProps
type ButtonProps = React.ComponentProps<'button'> & {variant: 'primary' | 'secondary';
};const Button = ({ variant, ...props }: ButtonProps) => {return <button className={`btn-${variant}`} {...props} />;
};

问题3:复杂状态结构

// 使用联合类型区分状态
type State = | { status: 'idle' }| { status: 'loading' }| { status: 'success'; data: User }| { status: 'error'; error: string };const UserProfile = () => {const [state, setState] = useState<State>({ status: 'idle' });switch (state.status) {case 'idle':return <button onClick={fetchUser}>Load User</button>;case 'loading':return <Spinner />;case 'success':return <UserData data={state.data} />;case 'error':return <ErrorMessage error={state.error} />;}
};

问题4:第三方组件类型

import { ExternalComponent } from 'third-party-library';// 扩展第三方组件Props
interface EnhancedProps {customProp: number;
}type CombinedProps = EnhancedProps & React.ComponentProps<typeof ExternalComponent>;const EnhancedComponent: React.FC<CombinedProps> = ({ customProp, ...props }) => {return <ExternalComponent {...props} />;
};

九、工具与资源

9.1 开发工具

  • TypeScript Playground:在线实验类型
  • React TypeScript Cheatsheet:社区最佳实践
  • ESLint + TypeScript:代码规范检查
  • VSCode 插件
    • ESLint
    • Prettier
    • TypeScript Importer

10. 总结

类型定义决策树

组件Props
联合类型/元组
定义类型
类型用途
使用接口 interface
使用类型别名 type
需要继承?
使用 extends
直接定义
需要复用?
提取到共享类型文件
内联定义

核心原则

  1. 显式优于隐式:明确定义所有类型
  2. 精确优于宽泛:使用最具体的类型
  3. 复用优于重复:提取共享类型
  4. 安全优于方便:避免 any 类型

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

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

相关文章

[1Prompt1Story] 注意力机制增强 IPCA | 去噪神经网络 UNet | U型架构分步去噪

第五章&#xff1a;注意力机制增强&#xff08;IPCA&#xff09; 欢迎回到1Prompt1Story&#x1f43b;‍❄️ 在第四章中&#xff0c;我们掌握了**语义向量重加权&#xff08;SVR&#xff09;**技术&#xff0c;通过语义向量调节实现核心要素强化。 但当场景从"雪地嬉戏…

【P7071 [CSP-J2020] 优秀的拆分 - 洛谷 https://www.luogu.com.cn/problem/P7071】

题目 P7071 [CSP-J2020] 优秀的拆分 - 洛谷 https://www.luogu.com.cn/problem/P7071 代码 #include <bits/stdc.h> using namespace std; const int N1e71; int d; vector<int> v; bool k[N]; bool fen(int x){if(x0)return 1;//能拆分完 for(int ix;i>x/…

从ioutil到os:Golang在线客服聊天系统文件读取的迁移实践

了解更多&#xff0c;搜索"程序员老狼"作为一名Golang开发者&#xff0c;我最近在维护一个客服系统时遇到了一个看似简单却值得深思的问题&#xff1a;如何将项目中遗留的ioutil.ReadFile调用迁移到现代的os.ReadFile。这看似只是一个简单的函数替换&#xff0c;但背…

Python UI自动化测试Web frame及多窗口切换

这篇文章主要为大家介绍了Python UI自动化测试Web frame及多窗口切换&#xff0c;有需要的朋友可以借鉴参考下&#xff0c;希望能够有所帮助&#xff0c;祝大家多多进步&#xff0c;早日升职加薪 一、什么是frame&frame切换&#xff1f; frame&#xff1a;HTML页面中的一…

工业相机基本知识解读:像元、帧率、数据接口等

工业相机&#xff08;Industrial Camera&#xff09;是一种专门为工业自动化和机器视觉应用而设计的成像设备&#xff0c;它不同于消费类相机&#xff08;如手机、单反&#xff09;&#xff0c;主要追求的是成像稳定性、长时间可靠性、实时性和精确性。它通常与镜头、光源、图像…

RTC之神奇小闹钟

&#x1f3aa; RTC 是什么&#xff1f;—— 电子设备的“迷你生物钟”想象一下&#xff1a;你晚上睡觉时&#xff0c;手机关机了。但当你第二天开机&#xff0c;它居然知道现在几点&#xff01;这就是 RTC&#xff08;Real-Time Clock&#xff0c;实时时钟&#xff09; 的功劳&…

判断IP是否属于某个网段

判断IP是否属于某个网段判断一个IP是否是否属于某个CIDR网段&#xff0c;核心是比较IP与网段的网络位是否一致&#xff0c;步骤如下&#xff1a; 一、明确CIDR网段的两个关键信息 假设要判断的IP是 IPx&#xff0c;目标网段是 CIDR 网段地址/n&#xff08;例如 192.168.1.0/24…

Python day50

浙大疏锦行 python day50. 在预训练模型&#xff08;resnet18&#xff09;中添加cbam注意力机制&#xff0c;需要修改模型的架构&#xff0c;同时应该考虑插入的cbam注意力机制模块的位置&#xff1b; import torch import torch.nn as nn from torchvision import models# 自…

VPS海外节点性能监控全攻略:从基础配置到高级优化

在全球化业务部署中&#xff0c;VPS海外节点的稳定运行直接影响用户体验。本文将深入解析如何构建高效的性能监控体系&#xff0c;涵盖网络延迟检测、资源阈值设置、告警机制优化等核心环节&#xff0c;帮助运维人员实现跨国服务器的可视化管控。 VPS海外节点性能监控全攻略&am…

C语言初学者笔记【结构体】

文章目录一、结构体的使用1. 结构体声明2. 变量创建与初始化3. 特殊声明与陷阱二、内存对齐1. 规则&#xff1a;2. 示例分析&#xff1a;3. 修改默认对齐数&#xff1a;三、结构体传参四、结构体实现位段1. 定义2. 内存分配3. 应用场景4. 跨平台问题&#xff1a;5. 注意事项&am…

基于XGBoost算法的数据回归预测 极限梯度提升算法 XGBoost

一、作品详细简介 1.1附件文件夹程序代码截图 全部完整源代码&#xff0c;请在个人首页置顶文章查看&#xff1a; 学行库小秘_CSDN博客​编辑https://blog.csdn.net/weixin_47760707?spm1000.2115.3001.5343 1.2各文件夹说明 1.2.1 main.m主函数文件 该MATLAB 代码实现了…

数据安全系列4:常用的对称算法浅析

常用的算法介绍 常用的算法JAVA实现 jce及其它开源包介绍、对比 传送门 数据安全系列1&#xff1a;开篇 数据安全系列2&#xff1a;单向散列函数概念 数据安全系列3&#xff1a;密码技术概述 时代有浪潮&#xff0c;就有退去的时候 在我的博客文章里面&#xff0c;其中…

云计算学习100天-第26天

地址重写地址重写语法——关于Nginx服务器的地址重写&#xff0c;主要用到的配置参数是rewrite 语法格式&#xff1a; rewrite regex replacement flag rewrite 旧地址 新地址 [选项]地址重写步骤&#xff1a;#修改配置文件(访问a.html重定向到b.html) cd /usr/local/ngin…

【Python办公】字符分割拼接工具(GUI工具)

目录 专栏导读 项目简介 功能特性 🔧 核心功能 1. 字符分割功能 2. 字符拼接功能 🎨 界面特性 现代化设计 用户体验优化 技术实现 开发环境 核心代码结构 关键技术点 使用指南 安装步骤 完整代码 字符分割操作 字符拼接操作 应用场景 数据处理 文本编辑 开发辅助 项目优势 …

Windows 命令行:dir 命令

专栏导航 上一篇&#xff1a;Windows 命令行&#xff1a;Exit 命令 回到目录 下一篇&#xff1a;MFC 第一章概述 本节前言 学习本节知识&#xff0c;需要你首先懂得如何打开一个命令行界面&#xff0c;也就是命令提示符界面。链接如下。 参考课节&#xff1a;Windows 命令…

软考高级--系统架构设计师--案例分析真题解析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言试题一 软件架构设计一、2019年 案例分析二、2020年 案例分析三、2021年 案例分析四、2022年 案例分析试题二 软件系统设计一、2019年 案例分析二、2020年 案例分…

css中的性能优化之content-visibility: auto

content-visibility: auto的核心机制是让浏览器智能跳过屏幕外元素的渲染工作&#xff0c;包括布局和绘制&#xff0c;直到它们接近视口时才渲染。这与虚拟滚动等传统方案相比优势明显&#xff0c;只需要一行CSS就能实现近似效果。值得注意的是必须配合contain-intrinsic-size属…

通过uniapp将vite vue3项目打包为android系统的.apk包,并实现可自动升级功能

打包vue项目,注意vite.config.ts文件和路由文件设置 vite.config.ts,将base等配置改为./ import {fileURLToPath, URL } from node:urlimport {defineConfig } from vite import vue from @vitejs/plugin-vue import AutoImport from unplugin-auto-import/vite import Com…

经营帮租赁经营板块:解锁资产运营新生态,赋能企业增长新引擎

在商业浪潮奔涌向前的当下&#xff0c;企业资产运营与租赁管理的模式不断迭代&#xff0c;“经营帮” 以其租赁经营板块为支点&#xff0c;构建起涵盖多元业务场景、适配不同需求的生态体系&#xff0c;成为众多企业破局资产低效困局、挖掘增长新动能的关键助力。本文将深度拆解…

C语言---编译的最小单位---令牌(Token)

文章目录C语言中令牌几类令牌是编译器理解源代码的最小功能单元&#xff0c;是编译过程的第一步。C语言中令牌几类 1、关键字&#xff1a; 具有固定含义的保留字&#xff0c;如 int, if, for, while, return 等。 2、标识符&#xff1a; 由程序员定义的名称&#xff0c;用于变…