JSX元素属性类型[...]可能不是联合类型

时间:2017-01-16 18:14:55

标签: reactjs typescript react-jsx

在Typescript 2.1中,尝试以下操作时:

// address.tsx
...
interface Address {
  street: string;
  country: string;
}

interface CanadianAddress extends Address {
  postalCode: string;
}

interface AmericanAddress extends Address {
  zipCode: string;
}

type Properties = AmericanAddress | CanadianAddress'

function isAmerican(address: Properties) address is AmericanAddress {
 return 'zipCode' in address;
}

export class Address extends React.Component<Properties, void> {
  public render() {
    let isAmerican = isAmerican(this.props.address);
    ...
  }
}

// map.tsx
...
let rootDiv = document.createElement('root')l
ReactDOM.render(<Address postalCode='T1B 0L3' />, rootDiv);

在编译时发生跟随错误:

  

错误TS2600:JSX元素属性类型'({children?:ReactNode;}&amp; AmericanAddress)| ({children?:ReactNode;}&amp; CanadianAddress'可能不是联合类型。

我想知道为什么不支持这个,以及如何在不指定过于复杂的属性的情况下完成此操作?

1 个答案:

答案 0 :(得分:0)

我不确定为什么它不可能,我能找到的只有@RyanCavanaugh:

  

我们并没有真正正确地支持JSX属性类型   联合类型

在问题中:Allow JSX element attributes type to be an intersection

解决这个问题的方法是有两个不同的组件,它们是Address的子类:

interface AddressProperties {
    street: string;
    country: string;
}

interface CanadianAddressProperties extends AddressProperties {
    postalCode: string;
}

interface AmericanAddressProperties extends AddressProperties {
    zipCode: string;
}

abstract class Address<P extends AddressProperties> extends React.Component<P, void> {
    public render() {
        return (
            <div className={ this.getClassName() + " address"}>
                <div><span>Street:</span><span>{ this.props.street }</span></div>
                <div><span>Country:</span><span>{ this.props.country }</span></div>
                {  }
            </div>
        );
    }

    protected abstract getClassName(): string;
    protected abstract getCountryElements(): JSX.Element | JSX.Element[];
}

class CanadianAddress extends Address<CanadianAddressProperties> {
    protected getClassName(): string {
        return "canadian";
    }

    protected getCountryElements(): JSX.Element {
        return <div><span>Postal Code:</span><span>{ this.props.postalCode }</span></div>;
    }
}

class AmericanAddress extends Address<AmericanAddressProperties> {
    protected getClassName(): string {
        return "american";
    }

    protected getCountryElements(): JSX.Element {
        return <div><span>Zip Code:</span><span>{ this.props.zipCode }</span></div>;
    }
}

如果两者之间的唯一变化是zipCode / postalCode,那么它可能是一种过度杀伤,但如果存在更多差异,则将两者分成不同的组件是有意义的。

否则,您需要在postalCode中将zipCodeAddressProperties作为可选项。