基于判别联合/泛型的Props无法被TypeScript推断
解决TypeScript条件Props推断失败的问题
问题本质
你的报错是因为TypeScript没法正确识别联合类型的分支,核心原因:
- 给
multipleSelection加默认值后,类型被自动拓宽成boolean,破坏了判别联合的类型区分逻辑 - 泛型方案里没让TypeScript自动推导
MS类型,同时默认值的类型约束没处理好
方案1:修复判别联合类型的类型收窄
把默认值移到函数内部处理,不要在参数解构时设置,保留联合类型的判别能力:
type DataFilteringBaseProps = { buttonClassname?: string; // 其他基础属性 }; type MultipleSelectionProps<T> = { multipleSelection: true; criteriaList: T[]; filtering: boolean; // 多选特有的属性 }; type SingleSelectionProps = { multipleSelection: false; // 单选特有的属性 }; type DataFilteringButtonProps<T extends string> = DataFilteringBaseProps & ( | SingleSelectionProps | MultipleSelectionProps<T> ); function DataFilteringButton<T extends string>( props: DataFilteringButtonProps<T> ) { // 内部处理默认值,不破坏联合类型 const { multipleSelection = false, buttonClassname, ...rest } = props; // 此时TypeScript能正确收窄类型 if (multipleSelection) { // rest自动推断为MultipleSelectionProps<T>类型,可直接访问filtering、criteriaList console.log(rest.criteriaList, rest.filtering); } else { // rest自动推断为SingleSelectionProps类型 console.log("单选模式"); } return <button className={buttonClassname}>筛选</button>; }
注意:不要在函数参数的解构中给multipleSelection设默认值,否则TypeScript会把它的类型从true | false拓宽成boolean,导致联合类型的判别失效。
方案2:优化泛型方案,实现自动类型推导
如果偏好泛型写法,要让TypeScript根据传入的props自动推导泛型参数,同时设置合理的默认值:
type DataFilteringBaseProps = { buttonClassname?: string; }; type MultipleSelectionProps<T> = { multipleSelection: true; criteriaList: T[]; filtering: boolean; }; type SingleSelectionProps = { multipleSelection: false; }; // 给MS设置默认泛型参数为false,对应单选模式 type DataFilteringButtonProps< T extends string, MS extends boolean = false > = DataFilteringBaseProps & (MS extends true ? MultipleSelectionProps<T> : SingleSelectionProps); function DataFilteringButton<T extends string, MS extends boolean = false>( props: DataFilteringButtonProps<T, MS> ) { const { multipleSelection = false as MS, buttonClassname } = props; if (multipleSelection) { // 此时props会自动推断为多选类型,可直接访问对应属性 console.log(props.criteriaList, props.filtering); } else { console.log("单选模式"); } return <button className={buttonClassname}>筛选</button>; } // 使用示例 DataFilteringButton({ multipleSelection: true, criteriaList: ["a", "b"], filtering: true }); DataFilteringButton({ multipleSelection: false }); DataFilteringButton({}); // 自动使用默认的单选模式
注意:给泛型MS设置默认值false,这样不传multipleSelection时会自动匹配单选类型;解构时用as MS约束默认值类型,避免类型拓宽。
避坑总结
- 判别联合类型的核心是保持判别属性的类型为
true | false,不要通过默认值把它变成boolean - 泛型方案尽量让TypeScript自动推导参数,不要手动指定,保证类型和传入的props匹配
内容的提问来源于stack exchange,提问作者user28586336
相关产品推荐
相关产品推荐

