如何基于字符串字面量类型定义TypeScript条件类型适配Redux Store?
解决TypeScript条件类型匹配Redux Store与React组件类型问题
没问题,我来帮你实现这个需求——让ILabelingStore的frames类型根据labelingType自动绑定,同时让React组件无需反复类型检查就能直接处理对应类型的数据。
第一步:定义类型映射表
先创建一个类型映射关系,把ILabelingTypes的每个取值对应到它专属的frames类型,后续可以通过索引直接获取对应类型:
type ILabelingTypes = "pedestrians" | "vehicles"; interface IFrame { url: string; orientation: number } // 建立labelingType与frames类型的映射 type LabelingFramesMap = { pedestrians: Map<string, IFrame[]>; vehicles: IFrame[]; };
第二步:创建泛型版ILabelingStore接口
用泛型来绑定labelingType和frames的类型关联,这样当指定labelingType时,frames的类型会被TypeScript自动推导:
interface ILabelingStore<T extends ILabelingTypes> { labelingType: T; frames: LabelingFramesMap[T]; }
现在你声明不同类型的store时,frames类型会自动匹配:
// 类型校验通过:frames自动为Map<string, IFrame[]> const pedestrianStore: ILabelingStore<"pedestrians"> = { labelingType: "pedestrians", frames: new Map([["group1", [{ url: "/frame1.jpg", orientation: 0 }]]]) }; // 类型校验通过:frames自动为IFrame[] const vehicleStore: ILabelingStore<"vehicles"> = { labelingType: "vehicles", frames: [{ url: "/car-frame.jpg", orientation: 90 }] };
第三步:Redux状态类型定义
如果你的Redux状态需要兼容两种store类型,可以用联合类型来表示:
type LabelingStoreState = ILabelingStore<"pedestrians"> | ILabelingStore<"vehicles">;
第四步:React组件无需类型检查直接使用
针对不同类型的store,我们可以创建接收特定泛型props的组件,组件内部的frames类型会被自动推断,完全不用手动校验:
Pedestrians专属组件
import React from "react"; type PedestriansProps = { store: ILabelingStore<"pedestrians">; }; class PedestriansComponent extends React.Component<PedestriansProps> { queue: IFrame[] = []; componentDidMount() { // frames自动识别为Map<string, IFrame[]>,直接用Object.entries遍历 Object.entries(this.props.store.frames).forEach(([key, val]) => { this.queue = this.queue.concat(val); }); } render() { return <div>行人标注组件</div>; } }
Vehicles专属组件
type VehiclesProps = { store: ILabelingStore<"vehicles">; }; class VehiclesComponent extends React.Component<VehiclesProps> { queue: IFrame[] = []; componentDidMount() { // frames自动识别为IFrame[],直接concat即可 this.queue = this.queue.concat(this.props.store.frames); } render() { return <div>车辆标注组件</div>; } }
可选:同一组件兼容两种类型(用类型守卫)
如果需要在单个组件里处理两种store类型,可以写类型守卫函数来缩小类型范围,避免手动类型断言:
// 类型守卫函数,帮助TypeScript识别store类型 function isPedestriansStore(store: LabelingStoreState): store is ILabelingStore<"pedestrians"> { return store.labelingType === "pedestrians"; } function isVehiclesStore(store: LabelingStoreState): store is ILabelingStore<"vehicles"> { return store.labelingType === "vehicles"; } // 通用标注组件示例 type GenericLabelingProps = { store: LabelingStoreState; }; class GenericLabelingComponent extends React.Component<GenericLabelingProps> { queue: IFrame[] = []; componentDidMount() { if (isPedestriansStore(this.props.store)) { // 此处frames自动为Map<string, IFrame[]> Object.entries(this.props.store.frames).forEach(([key, val]) => { this.queue = this.queue.concat(val); }); } else if (isVehiclesStore(this.props.store)) { // 此处frames自动为IFrame[] this.queue = this.queue.concat(this.props.store.frames); } } render() { return <div>通用标注组件</div>; } }
这样实现后,TypeScript会全程帮你做类型校验,再也不用在组件里反复写类型检查或者手动断言啦!
内容的提问来源于stack exchange,提问作者John Ruddell
相关产品推荐
相关产品推荐

