react-aria中useTabListState相关类型查找及使用疑问求助
为React Aria Tabs组件添加类型定义的问题
我正在测试react-aria的Tabs组件,尝试为其官方示例添加类型定义。问题在于,我不确定Tabs组件的props应使用哪种类型。useTabListState依赖TabListStateOptions类型,但我在相关包中找不到它,查看仓库后发现该类型并未在库中导出。
请问我是否应该使用node_modules中的类型?有没有遗漏的类型查找方法?
当前代码(不含CSS及使用部分)
import {useTab, useTabList, useTabPanel} from 'react-aria'; import {Item, useTabListState} from 'react-stately'; function Tabs(props) { let state = useTabListState(props); let ref = React.useRef(null); let { tabListProps } = useTabList(props, state, ref); return ( <div className={`tabs ${props.orientation || ''}`}> <div {...tabListProps} ref={ref}> {[...state.collection].map((item) => ( <Tab key={item.key} item={item} state={state} orientation={props.orientation} /> ))} </div> <TabPanel key={state.selectedItem?.key} state={state} /> </div> ); } function Tab({ item, state, orientation }) { let { key, rendered } = item; let ref = React.useRef(null); let { tabProps } = useTab({ key }, state, ref); return ( <div {...tabProps} ref={ref}> {rendered} </div> ); } function TabPanel({ state, ...props }) { let ref = React.useRef(null); let { tabPanelProps } = useTabPanel(props, state, ref); return ( <div {...tabPanelProps} ref={ref}> {state.selectedItem?.props.children} </div> ); }
解决方法
提取未导出的类型
利用TypeScript的Parameters工具类型,从useTabListState的参数中直接提取所需类型,无需依赖未导出的TabListStateOptions:import { useTabListState } from 'react-stately'; // 提取useTabListState的第一个参数类型 type TabListStateOptions = Parameters<typeof useTabListState>[0];直接将此类型用于
Tabs组件的props:function Tabs(props: TabListStateOptions) { // 原有逻辑不变 }扩展自定义props
如果需要添加自定义属性(比如额外的className),可以扩展提取到的类型:type TabsProps = TabListStateOptions & { className?: string; }; function Tabs(props: TabsProps) { // 原有逻辑不变 }不建议直接引用node_modules类型
直接导入node_modules内的类型文件会导致依赖路径不稳定,库版本更新时容易出现类型断裂问题,使用上述类型提取方式更可靠。补充其他组件的类型
对于Tab和TabPanel,可以通过ReturnType和类型推导提取所需类型:// 提取useTabListState的返回值类型 type TabListState = ReturnType<typeof useTabListState>; // 提取集合中item的类型 type TabItem = typeof useTabListState extends () => infer S ? S['collection'] extends Iterable<infer I> ? I : never : never;完整的带类型代码参考:
import { useTab, useTabList, useTabPanel } from 'react-aria'; import { Item, useTabListState } from 'react-stately'; import React from 'react'; type TabListStateOptions = Parameters<typeof useTabListState>[0]; type TabListState = ReturnType<typeof useTabListState>; type TabItem = typeof useTabListState extends () => infer S ? S['collection'] extends Iterable<infer I> ? I : never : never; type TabsProps = TabListStateOptions; function Tabs(props: TabsProps) { let state = useTabListState(props); let ref = React.useRef<HTMLDivElement>(null); let { tabListProps } = useTabList(props, state, ref); return ( <div className={`tabs ${props.orientation || ''}`}> <div {...tabListProps} ref={ref}> {[...state.collection].map((item) => ( <Tab key={item.key} item={item} state={state} orientation={props.orientation} /> ))} </div> <TabPanel key={state.selectedItem?.key} state={state} /> </div> ); } type TabProps = { item: TabItem; state: TabListState; orientation?: TabListStateOptions['orientation']; }; function Tab({ item, state, orientation }: TabProps) { let { key, rendered } = item; let ref = React.useRef<HTMLDivElement>(null); let { tabProps } = useTab({ key }, state, ref); return ( <div {...tabProps} ref={ref}> {rendered} </div> ); } type TabPanelProps = { state: TabListState; } & React.HTMLAttributes<HTMLDivElement>; function TabPanel({ state, ...props }: TabPanelProps) { let ref = React.useRef<HTMLDivElement>(null); let { tabPanelProps } = useTabPanel(props, state, ref); return ( <div {...tabPanelProps} ref={ref}> {state.selectedItem?.props.children} </div> ); }
内容的提问来源于stack exchange,提问作者Artur Carvalho
相关产品推荐
相关产品推荐

