英文:
Conditional props in intreface
问题
我有一个关于接口的问题:
基本上,我正在创建一个动态组件,它根据所在的页面而变化。我的接口构建如下:
interface Props {
heading: string;
description: string;
signUp?: boolean;
signUpButton1?: string;
signUpButtonLink1?: string;
signUpButton2?: string;
signUpButtonLink2?: string;
startFreeAccount?: boolean;
startFreeAccountSignUpButton?: string;
startFreeAccountLink1?: string;
startFreeAccountSignUpLink1?: string;
startFreeAccountSignUpLink2?: string;
startFreeAccountSignUpLink3?: string;
contactUsForDemo?: boolean;
contactUsForDemoInput1?: string;
contactUsForDemoInput2?: string;
contactUsForDemoInput3?: string;
contactUsForDemoButtonText?: string;
ThanksForDemo?: boolean;
ThanksForDemoButton?: string;
}
然后,在我的代码中,例如使用:
{props.signUp &&
<div className="mt-10 flex flex-col items-center gap-x-6">
<Link
href={"/signUpPractitioner/startFreeAccount"}
className="bg-black mb-4 -ml-[14vw] px-16 py-1.5 text-base font-semibold leading-7 text-white shadow-sm outline outline-offset-0 outline-black"
>
{props.signUpButton1}
</Link>
<Link href={"/practitioner/contactUsForDemo"}
className="bg-white -ml-[14vw] px-10 py-1.5 text-base font-semibold leading-7 text-black outline outline-offset-0 outline-black shadow-sm"
>
{props.signUpButton2} <span aria-hidden="true">→</span>
</Link>
</div>
}
设置 "signUp == true" 将显示组件上面部分的信息。我的问题是,Link(来自NEXTJS)无法处理 "signUpButtonLink1" 可能未定义的情况。如果我要求 "signUpButtonLink1" 必须有一个值,那么即使我不使用组件的 "signUp" 部分,我仍然需要为 "signUpButtonLink1" 赋予某个值,这显然是没有意义的(从当前接口构建的角度来看是有意义的,但从功能角度来看不合理)。
我的问题是:是否可以设置 "signUpButton1、signUpLink1等等" 只需要在 "signUp === true" 的情况下设置?对于接口中的所有布尔值和与之相关的 props 都适用相同的规则。
感谢您的帮助!
英文:
I have a question regarding interfaces:
Basically I'm creating a dynamic component that change depending on which page it is. My interface is constructed like so:
interface Props {
heading: string;
description: string;
signUp?: boolean;
signUpButton1?: string;
signUpButtonLink1?: string;
signUpButton2?: string;
signUpButtonLink2?: string;
startFreeAccount?: boolean;
startFreeAccountSignUpButton?: string;
startFreeAccountLink1?: string;
startFreeAccountSignUpLink1?: string;
startFreeAccountSignUpLink2?: string;
startFreeAccountSignUpLink3?: string;
contactUsForDemo?: boolean;
contactUsForDemoInput1?: string;
contactUsForDemoInput2?: string;
contactUsForDemoInput3?: string;
contactUsForDemoButtonText?: string;
ThanksForDemo?: boolean;
ThanksForDemoButton?: string;
}
In my code I then use for example:
{props.signUp &&
<div className="mt-10 flex flex-col items-center gap-x-6">
<Link
href={"/signUpPractitioner/startFreeAccount"}
className=" bg-black mb-4 -ml-[14vw] px-16 py-1.5 text-base font-semibold leading-7 text-white shadow-sm outline outline-offset-0 outline-black"
>
{props.signUpButton1}
</Link>
<Link href={"/practitioner/contactUsForDemo"}
className=" bg-white -ml-[14vw] px-10 py-1.5 text-base font-semibold leading-7 text-black outline outline-offset-0 outline-black shadow-sm"
>
{props.signUpButton2} <span aria-hidden="true">→</span>
</Link>
</div> }
Setting "signUp == true" would display the information in the above part of the component. My issue is that Link (from NEXTJS) cannot handle the fact that "signUpButtonLink1" might be undefined. If I put that "signUpButtonLink1" has to have a value, then even if I don't use the "signUp" part of the component, I still need to assign some value to "signUpButtonLink1" which obviously doesnt make sense (it makes sense in terms of how the current interface is constructed but not in terms of functionality).
My question is: Is it possible to set that "signUpButton1, signUpLink1 etc etc" only needs to be set if "signUp === true" ? It the same for all bools in the interface and the props "affiliated" with it.
Thanks for your help!
答案1
得分: 1
你可以使用简单的联合类型来实现这个。
```ts
type Props = {
heading: string;
description: string;
} & (
| {
signUp?: false
signUpButton1?: never
// ...
}
| {
signUp: true
signUpButton1: string
// ...
}
) & (
| {
startFreeAccount?: false;
startFreeAccountSignUpButton?: never;
// ...
}
| {
startFreeAccount: true;
startFreeAccountSignUpButton: string;
// ...
}
) & (
...
)
也许可以添加一个实用类型:
type OptionalProps<K extends string, T> =
| { [key in K]?: false } & { [key in keyof T]?: never }
| { [key in K]: true } & T
type Props = {
heading: string
description: string
}
& OptionalProps<'signUp', {
signUpButton1: string,
}>
& OptionalProps<'startFreeAccount', {
startFreeAccountSignUpButton: string
}>
& ...
具有 ?: never
的属性并不是必需的,但如果你将 props 解构为单独的变量,它们会让你的生活更轻松。如果没有 ?: never
,它会告诉你对象中不存在名为 ...
的属性。
或者你可以只是使用对象而不是内联 props:
type Props = {
heading: string
description: string
signUp?: {
button1: string
button2: string
// ...
}
startFreeAccount?: {
signUpButton: string
// ...
}
// ...
}
我甚至会认为这些对象更容易阅读和使用。
<details>
<summary>英文:</summary>
You can do this with simple unions
```ts
type Props = {
heading: string;
description: string;
} & (
| {
signUp?: false
signUpButton1?: never
// ...
}
| {
signUp: true
signUpButton1: string
// ...
}
) & (
| {
startFreeAccount?: false;
startFreeAccountSignUpButton?: never;
// ...
}
| {
startFreeAccount: true;
startFreeAccountSignUpButton: string;
// ...
}
) & (
...
)
Maybe add a utility type:
type OptionalProps<K extends string, T> =
| { [key in K]?: false } & { [key in keyof T]?: never }
| { [key in K]: true } & T
type Props = {
heading: string
description: string
}
& OptionalProps<'signUp', {
signUpButton1: string,
}>
& OptionalProps<'startFreeAccount', {
startFreeAccountSignUpButton: string
}>
& ...
The properties with ?: never
are not necessary, but they will make your life easier if you destructure props into individual variables. Without ?: never
you won't be able to do it, it will tell that property with name ...
doesn't exist in the object.
Or you can just use objects instead of inline props:
type Props = {
heading: string
description: string
signUp?: {
button1: string
button2: string
// ...
}
startFreeAccount?: {
signUpButton: string
// ...
}
// ...
}
I would even argue that these objects is easier to read and use
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论