isLink
先前的示例工作,如果我将href定义为可选的未定义属性,则是这样的:
const Mycomponent = <Logo label="payment" variant="paypal" href="http://paypal.com" />
// error because isLink is missing and we are using 'href'
const Mycomponent = <Logo isLink label="payment" variant="paypal" href="http://paypal.com" />
// correct because isLink is true and therefore we need and 'href'
如果在接口徽标中,则删除您不会遇到任何错误的“ HREF”属性(我希望它具有错误):
import React, { FC } from "react";
type ValidRel = "alternate" | "author" | "bookmark";
export type LinkProps = {
rel?: ValidRel;
href: string;
target?: "_blank" | "_self" | "_parent" | "_top";
};
interface CommonProps {
variant: "paypal" | "visa" | "mastercard";
className?: string;
};
interface LogoBase extends CommonProps {
label?: string;
};
interface Logo extends LogoBase {
isLink?: false;
// if you remove the line below you have a Logo without "isLink" property
// and a "href" property (which should be wrong combination)
href?: undefined;
};
interface InteractiveLogo extends LogoBase, LinkProps {
isLink: true;
label: string;
};
export type Props = InteractiveLogo | Logo;
const Logo: FC<Props> = ({ variant, label, className, ...unionProps }) => {
if ("href" in unionProps) {
return (
<a {...unionProps}>
<p className={className} aria-label={label}>{variant} </p>
</a>
);
}
return <p className={className} aria-label={label}>{variant} </p>
};
const Mycomponent = <Logo label="payment" variant="paypal" href="http://paypal.com" />
如果我像字符串的结合而不是字符串键入“ HREF”,那么更奇怪的是,它可以正如我期望的那样恢复正常。当然,“ HREF”不能固定字符串,因为将是提供的任何URL:
interface Logo extends LogoBase {
isLink?: false;
//removed: href?: undefined;
};
Playground
您正在推动类型系统来执行要做的组件要做的事情 - 最好将实现分开:
export type LinkProps = {
rel?: ValidRel;
href: "www.goole.es" | "www.hotmail.com"; // this union makes the types work OK again
target?: "_blank" | "_self" | "_parent" | "_top";
};
和
const Logo: FC<Logo> = ({ variant, label, className }) => (
<p className={className} aria-label={label}>
{variant}{" "}
</p>
);
风格注意:很容易不要重复自己并删除所有内容,但是只需要始终需要始终相同的代码。
注意,在最高建议中感觉就像重复,但是重复的唯一行是方法的参数。