React TypeScript:如何兼顾获取枚举类型与传递只读对象作为Props
问题描述
我有如下数据:
const ActionData = [ { label: 'Edit', icon: 'pen', key: 'edit' }, { label: 'Skip', icon: 'forward', key: 'skip' }, { label: 'Stop', icon: 'stop-circle', key: 'stop' }, ];
用它来渲染ActionItem组件列表:
{ActionData.map((dataItem) => ( <ActionItem key={dataItem.key} item={dataItem} onPress={handleActionClick} /> ))}
我需要一个类型ActionItemKeyType,其值应为'edit' | 'skip' | 'stop',也就是ActionData的key值集合。
如果把ActionData声明为只读数组:
const ActionData = [ { label: 'Edit', icon: 'pen', key: 'edit' }, { label: 'Skip', icon: 'forward', key: 'skip' }, { label: 'Stop', icon: 'stop-circle', key: 'stop' }, ] as const;
就能通过以下代码得到预期的ActionItemKeyType:
type ActionItemKeyType = typeof ActionData[number]['key'];
但这样声明后数组变为只读,渲染时无法将item作为Props传递。请问如何同时实现提取精确key类型和数组可用于组件Props传递这两个功能?
解决方案
方法一:先定义只读数组提取类型,再创建可变副本
先通过as const声明只读数组来提取类型,再用扩展运算符创建可变数组副本用于渲染:
// 只读数组,仅用于提取类型 const _ActionData = [ { label: 'Edit', icon: 'pen', key: 'edit' }, { label: 'Skip', icon: 'forward', key: 'skip' }, { label: 'Stop', icon: 'stop-circle', key: 'stop' }, ] as const; // 提取目标key类型 type ActionItemKeyType = typeof _ActionData[number]['key']; // 创建可变数组,用于组件渲染 const ActionData = [..._ActionData];
这样ActionData是可变数组,可正常传递给组件Props,同时ActionItemKeyType能精确得到'edit' | 'skip' | 'stop'的联合类型。
方法二:先定义基础类型,再推导数组和key类型
先定义单个数据项的类型,再基于此推导数组类型和key类型,同时保证数组可变性:
// 定义单个动作项的类型,明确key的可选值 type ActionItem = { label: string; icon: string; key: 'edit' | 'skip' | 'stop'; }; // 声明可变数组,类型约束为ActionItem[] const ActionData: ActionItem[] = [ { label: 'Edit', icon: 'pen', key: 'edit' }, { label: 'Skip', icon: 'forward', key: 'skip' }, { label: 'Stop', icon: 'stop-circle', key: 'stop' }, ]; // 提取key类型 type ActionItemKeyType = ActionItem['key'];
这种方法逻辑直接,但需要手动维护ActionItem中的key联合类型,后续新增动作项时需同步更新类型定义和数组内容。
方法三:类型断言解除只读限制(谨慎使用)
如果不想创建数组副本,可在传递Props时用类型断言解除单个item的只读限制:
const ActionData = [ { label: 'Edit', icon: 'pen', key: 'edit' }, { label: 'Skip', icon: 'forward', key: 'skip' }, { label: 'Stop', icon: 'stop-circle', key: 'stop' }, ] as const; type ActionItemKeyType = typeof ActionData[number]['key']; // 渲染时断言item为非只读类型 {ActionData.map((dataItem) => ( <ActionItem key={dataItem.key} item={dataItem as Omit<typeof dataItem, never>} onPress={handleActionClick} /> ))}
注意:此方法会绕过TypeScript的只读检查,若组件Props会修改item内容,可能引发意外问题,仅在确定组件不会修改item时使用。
内容的提问来源于stack exchange,提问作者kashif-sk
相关产品推荐
相关产品推荐

