基于属性值的条件类型:TypeScript组件Props类型定义难题
解决TypeScript中组件Props的条件类型依赖问题
你遇到的问题很典型——在TypeScript里直接在对象类型中用属性值做条件判断是行不通的,因为类型定义层面无法直接引用属性名作为判断依据。不过我们可以用判别式联合类型(Discriminated Union)来完美解决这个需求,让onToggle的类型严格依赖collapsible的取值。
具体实现方式
我们可以把组件的Props拆分成两种明确的类型,再合并成联合类型:
// 当collapsible为true时,onToggle必须是一个无参函数 type CollapsibleStateProps = { collapsible: true; onToggle: () => void; }; // 当collapsible为false时,onToggle必须是undefined type NonCollapsibleStateProps = { collapsible: false; onToggle: undefined; }; // 合并成最终的Props类型 type Props = CollapsibleStateProps | NonCollapsibleStateProps;
为什么这样可行?
这里的collapsible就是一个判别式——TypeScript会根据它的布尔值,自动推断出当前Props对应的子类型。在组件内部使用时,TypeScript还会帮你做类型收窄:
const MyComponent = (props: Props) => { if (props.collapsible) { // 此时TypeScript知道props属于CollapsibleStateProps,onToggle是安全可调用的 props.onToggle(); } else { // 此时props属于NonCollapsibleStateProps,onToggle是undefined,调用会直接报错 // props.onToggle(); // ❌ TypeScript会提示错误 } return <div>...</div>; };
额外优化:让onToggle在不可折叠时可选
如果你希望当collapsible为false时,onToggle可以省略不传递(而不是必须传undefined),可以把NonCollapsibleStateProps改成这样:
type NonCollapsibleStateProps = { collapsible: false; onToggle?: undefined; };
这样用户使用组件时,当collapsible={false},可以完全不写onToggle属性,TypeScript也不会报错。
泛型方案(可选)
如果你更倾向于用泛型来实现,也可以这样定义:
type Props<T extends boolean> = { collapsible: T; onToggle: T extends true ? () => void : undefined; };
不过这种方式需要用户在使用组件时显式指定泛型参数(比如<MyComponent<true> collapsible={true} onToggle={() => {...}} />),不如联合类型的方式灵活,所以一般更推荐前者。
内容的提问来源于stack exchange,提问作者Tomasz Staszkiewicz
相关产品推荐
相关产品推荐

