两组条件Props触发报错:boolean类型无法赋值给false类型
问题原因
TypeScript无法将Boolean(orthoData)返回的动态boolean变量自动推断为true或false字面量类型,导致组件的联合类型条件分支匹配到了hasOpacitySlider?: false | undefined和hasVisibilityToggle?: false | undefined的分支,进而要求相关属性必须为undefined,但你实际传入了有效值,因此触发类型错误。
解决方案
方案1:用类型谓词缩小变量类型
自定义类型守卫,明确告诉TypeScript变量的字面量类型,让联合类型分支正确匹配:
// 定义类型谓词,判断变量是否为true字面量类型 function isTrue(value: boolean): value is true { return value === true; } // 使用时通过分支渲染匹配对应类型 const hasOrthoData = Boolean(orthoData); {isTrue(hasOrthoData) ? ( <LayerItem hasOpacitySlider={hasOrthoData} hasVisibilityToggle={hasOrthoData} isVisible={showOrthoLayer} opacitySliderSetter={setOrthoLayerOpacity} opacitySliderState={orthoLayerOpacity} onChangeVisibility={setShowOrthoLayer} label="Orthophoto" /> ) : ( <LayerItem label="Orthophoto" /> )}
方案2:改为泛型组件
将hasOpacitySlider和hasVisibilityToggle作为泛型参数,让组件根据泛型值推断必填属性,动态变量也能正确适配:
import { Dispatch, SetStateAction, FC, ReactNode } from 'react'; export interface Props { label: string; children?: ReactNode; } // 基于泛型的条件属性类型 type OpacityConditionalProp<HasSlider extends boolean> = HasSlider extends true ? { hasOpacitySlider: true; opacitySliderState: number | number[]; opacitySliderSetter: Dispatch<SetStateAction<number | number[]>>; } : { hasOpacitySlider?: false | undefined; opacitySliderState?: undefined; opacitySliderSetter?: undefined; }; type VisibilityConditionalProp<HasToggle extends boolean> = HasToggle extends true ? { hasVisibilityToggle: true; isVisible: boolean; onChangeVisibility: (v: boolean) => void; } : { hasVisibilityToggle?: false | undefined; isVisible?: undefined; onChangeVisibility?: undefined; }; // 定义泛型组件 const LayerItem = < HasSlider extends boolean = false, HasToggle extends boolean = false >( props: Props & OpacityConditionalProp<HasSlider> & VisibilityConditionalProp<HasToggle> ) => { /* 组件逻辑 */ }; // 使用时通过`as const`强制推断字面量类型 const hasOrthoData = Boolean(orthoData) as const; <LayerItem hasOpacitySlider={hasOrthoData} hasVisibilityToggle={hasOrthoData} isVisible={showOrthoLayer} opacitySliderSetter={setOrthoLayerOpacity} opacitySliderState={orthoLayerOpacity} onChangeVisibility={setShowOrthoLayer} label="Orthophoto" />
方案3:简化条件类型结构
拆分条件属性为独立接口,用Partial和交叉类型结合,牺牲部分严格性换取灵活性:
import { Dispatch, SetStateAction, FC, ReactNode } from 'react'; export interface Props { label: string; children?: ReactNode; } // 独立的滑块属性接口 interface OpacitySliderProps { hasOpacitySlider: true; opacitySliderState: number | number[]; opacitySliderSetter: Dispatch<SetStateAction<number | number[]>>; } // 独立的可见性切换属性接口 interface VisibilityToggleProps { hasVisibilityToggle: true; isVisible: boolean; onChangeVisibility: (v: boolean) => void; } // 组件类型:基础Props + 可选的两组条件属性 const LayerItem: FC< Props & Partial<OpacitySliderProps> & Partial<VisibilityToggleProps> > = ({ label, hasOpacitySlider, opacitySliderState, opacitySliderSetter, isVisible, onChangeVisibility, hasVisibilityToggle, children, }) => { // 组件内部判断hasXXX为true时,用非空断言或运行时检查确保属性存在 if (hasOpacitySlider) { const state = opacitySliderState!; const setter = opacitySliderSetter!; // 执行滑块相关逻辑 } // 其他组件逻辑 }; // 使用时无类型错误 const hasOrthoData = Boolean(orthoData); <LayerItem hasOpacitySlider={hasOrthoData} hasVisibilityToggle={hasOrthoData} isVisible={showOrthoLayer} opacitySliderSetter={setOrthoLayerOpacity} opacitySliderState={orthoLayerOpacity} onChangeVisibility={setShowOrthoLayer} label="Orthophoto" />
内容的提问来源于stack exchange,提问作者Razvan
相关产品推荐
相关产品推荐

