如何在对象配置中关联Record键与对应React.FC子类型
问题与解决方案
原始代码
import React, { ReactElement, FC } from 'react'; type BaseDisplayMode = { label: 'string', value: 'string', 'displayName': string}; type DisplayModeA = BaseDisplayMode & { mode: 'a', a: string}; type DisplayModeB = BaseDisplayMode & { mode: 'b', b: string}; type DisplayModes = DisplayModeA | DisplayModeB; const displayModeA = (p: DisplayModeA): ReactElement => (<div> Hello </div>); const displayModeB = (p: DisplayModeB): ReactElement => (<div> Hello </div>); const strategyProperty: Record<DisplayModes['mode'], FC<DisplayModes>>= { a: displayModeA, b: displayModeB, }
问题
我该如何确保Record的键a仅自动接受displayModeA,键b仅自动接受displayModeB?
解决方案
首先修正BaseDisplayMode的类型错误(原代码中label: 'string'是字符串字面量类型,应改为string类型,否则会限制属性值只能是'string'这个固定字符串),然后通过映射类型为每个mode绑定对应的组件props类型:
import React, { ReactElement, FC } from 'react'; // 修正BaseDisplayMode的类型定义 type BaseDisplayMode = { label: string, value: string, displayName: string}; type DisplayModeA = BaseDisplayMode & { mode: 'a', a: string}; type DisplayModeB = BaseDisplayMode & { mode: 'b', b: string}; type DisplayModes = DisplayModeA | DisplayModeB; // 创建映射类型:每个mode对应到其专属的组件类型 type ModeComponentMap = { [M in DisplayModes['mode']]: FC<Extract<DisplayModes, { mode: M }>> }; const displayModeA = (p: DisplayModeA): ReactElement => (<div> Hello Mode A </div>); const displayModeB = (p: DisplayModeB): ReactElement => (<div> Hello Mode B </div>); // 使用自定义映射类型替代Record const strategyProperty: ModeComponentMap = { a: displayModeA, // 类型匹配,无报错 b: displayModeB, // 类型匹配,无报错 // 若尝试把displayModeB赋值给a,TypeScript会直接报错 // a: displayModeB // 类型错误:类型'(p: DisplayModeB) => ReactElement'不能赋值给类型'FC<DisplayModeA>' };
关键说明
Extract工具类型:Extract<DisplayModes, { mode: M }>会从联合类型DisplayModes中提取出mode属性等于M的具体类型,比如当M为'a'时,提取出的就是DisplayModeA。- 映射类型
ModeComponentMap:遍历所有DisplayModes的mode值,为每个mode键指定对应的组件类型(只能接受该mode专属props的FC),以此实现键与组件的严格绑定。
内容的提问来源于stack exchange,提问作者Swastik Pareek
相关产品推荐
相关产品推荐

