我有一个Test
组件,它必须接受一个one
属性,其中对象必须有一个a
字段,但只有一个id
字段 * 如果 * 没有提供two
属性。如果提供了two
属性,则one
属性的对象必须没有id
字段。
如何才能做到这一点?我能得到的最接近的方法是使用以下界面:
interface Test {
one: {
a: string;
id?: number;
};
two?: number;
}
显然,它不会正常工作,因为id
字段和two
属性只是设置为可选,而不是相互调节。
下面是我构建的演示:
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>;
};
堆栈 lightning 战演示:https://stackblitz.com/edit/react-ts-2wsnwj?file=App.tsx
我想知道我是否可以这样写类型,但显然不行:
type One = {
a: string
id?: number
}
type Two = One.id ? number : null
如有任何建议,我将不胜感激,谢谢
更新:
我刚刚意识到我接受的答案是错误的,因为它仍然期待prop two
所有的时间,因此在这个演示中的两个组件的错误(https://stackblitz.com/edit/react-ts-owrj8a?file=App.tsx)。
我试图把它从答案改成这样:
interface A {
a: string;
}
interface OptionOne {
one: A & {
id: number;
};
two: never;
}
interface OptionTwo {
one: A;
two: number;
}
type FinalType = OptionOne | OptionTwo;
// type Test =
// | { one: { a: string; id: number } }
// | { one: { a: string }; two: number };
const Test = ({ one, two }: FinalType): JSX.Element => {
return <p>test</p>;
};
但它有同样的效果。有人知道解决这个问题的方法吗?
未提供prop two
时的错误:
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'
1条答案
按热度按时间vwhgwdsa1#
使
Test
成为涵盖所有可接受状态的联合类型:在OP评论后编辑:
你现在面临的问题并不奇怪,TypeScript不允许你从
props
反结构two
,因为你已经告诉过在某些情况下这个属性不存在。在这种情况下,您可以手动检查
two
字段是否存在,如果存在,则使用它。现在错误已经消失了。