React TypeScript组件中如何实现Props的互斥条件类型约束?
解决Test组件Props的条件类型约束问题
需求说明
- Test组件必须接收
oneprop,该对象必须包含a字段 - 未提供
twoprop时,one必须包含id字段 - 提供
twoprop时,one不能包含id字段
最初的无效尝试
以下接口无法实现one和two的条件关联:
interface Test { one: { a: string; id?: number; }; two?: number; }
演示代码
export default function App() { return ( <div> <Test one={{ a: 'valid example with id and no two prop', id: 5, }} /> <Test one={{ a: 'valid example with two prop and no id field', }} two={9} /> <Test one={{ a: 'should have id or two prop; needs to error', }} /> <Test one={{ a: 'cannot have both id field AND two prop; needs to error', id: 2, }} two={5} /> </div> ); } interface Test { one: { a: string; id?: number; }; two?: number; } const Test = ({ one, two }: Test): JSX.Element => { return <p>test</p>; };
错误的类型尝试
以下写法无法生效:
type One = { a: string id?: number } type Two = One.id ? number : null
更新的问题
之前的方案存在缺陷,会强制要求必须提供two prop,导致合法的组件实例报错。修改后的代码仍未解决问题:
interface A { a: string; } interface OptionOne { one: A & { id: number; }; two: never; } interface OptionTwo { one: A; two: number; } type FinalType = OptionOne | OptionTwo; const Test = ({ one, two }: FinalType): JSX.Element => { return <p>test</p>; };
报错信息
Type '{ one: { a: string; }; }' is not assignable to type 'IntrinsicAttributes & FinalType'. Property 'two' is missing in type '{ one: { a: string; }; }' but required in type 'OptionTwo'
解决方案
通过调整联合类型的定义,让two在不需要时可省略,同时约束one的结构:
interface BaseOne { a: string; } type TestProps = // 情况1:不传递two,one必须包含id { one: BaseOne & { id: number }; two?: never; } // 情况2:传递two,one不能包含id | { one: BaseOne & { id?: never }; two: number; }; const Test = ({ one, two }: TestProps): JSX.Element => { return <p>test</p>; };
说明
- 第一个分支中,
two?: never表示two可以不传递,此时TypeScript会匹配该分支,强制one必须包含id字段。 - 第二个分支中,
id?: never限制one不能有id字段(never类型无有效值),同时要求必须传递two。
该定义可完全满足需求:
- 合法实例(带
id无two、带two无id)可正常通过类型检查 - 非法实例(无
id无two、带id带two)会触发TypeScript错误
内容的提问来源于stack exchange,提问作者user8758206
相关产品推荐
相关产品推荐

