【问题标题】:JSX element attributes type [...] may not be a union typeJSX 元素属性类型 [...] 可能不是联合类型
【发布时间】:2017-05-31 15:49:25
【问题描述】:

在 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; } & AmericanAddress) | ({ children?: ReactNode; } & CanadianAddress' 可能不是联合类型。

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

【问题讨论】:

标签: reactjs typescript react-jsx


【解决方案1】:

我不知道为什么这是不可能的,我只能找到@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 和zipCode 作为可选的AddressProperties。

【讨论】:

    猜你喜欢
    • 2017-03-09
    • 1970-01-01
    • 1970-01-01
    • 2019-07-21
    • 2018-02-08
    • 2019-11-24
    • 2020-05-31
    • 1970-01-01
    • 2019-05-29
    相关资源
    最近更新 更多