TypeScript相交类型

时间:2019-06-26 07:29:05

标签: reactjs typescript typescript-typings

我有一些typescript这样的定义:

interface T1 { 
    children: string[];
}

interface T2 {
    children?: number | boolean | undefined | null;
}

type All = T1 & T2;

const b: All = {
    children: ['test'],
};

请参阅typescript playground

我想知道All[‘children’]属性到底是什么类型?

我无法为其分配string array,也不知道如何使用此intersection type

在现实生活中,React.jschildren上有一个React.Component定义,当我定义自己的children类型时,在这种情况下没有错误。

更新,在React Native代码中添加一些真实的代码。我有以下定义:

interface Props {
    children: View[];
}

export default Demo extends React.Component<Props> {

}

// later in parent component
<Demo>
    <View></View>
    <View></View>
</Demo>

我不知道为什么typescript可以处理children的{​​{1}}。这是Demo

中的children定义
React.Component

因此,我认为{ children?: ReactChild | ReactFragment | ReactPortal | boolean | null | undefined; } type的最后children应该是:

Demo

如何将children: (View[] & ReactChild) | (View[] & ReactFragment) | (View[] & ReactPortal) | (View[] & boolean) | (View[] & null) | (View[] & undefined) 传递给View arrays作为孩子。

再次更新,我发现Demo的定义是关键。

ReactFragment
type ReactFragment = {} | ReactNodeArray; type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined; 中的

{},结果为ReactFragment,相当于View[] & {}

2 个答案:

答案 0 :(得分:0)

交叉点类型意味着可分配给该类型的实例必须可分配给交叉点的组成部分。这将导致编译器将children键入为string[] & (number | boolean | undefined | null),这是一种很难实现的类型,可能无论如何都不是您想要的。

如果您希望AllT1T2,则必须使用并集:

interface T1 { 
    children: string[];
}

interface T2 {
    children?: number | boolean | undefined | null;
}

type All = T1 | T2;

const b: All = { // OK
    children: ['test'],
};

或者,如果您需要更复杂的合并逻辑,请提供更多详细信息。

答案 1 :(得分:0)

当我阅读React.ReactNode定义时,我错过了这一点。定义如下:

type ReactText = string | number;
type ReactChild = ReactElement | ReactText;

interface ReactNodeArray extends Array<ReactNode> {}
type ReactFragment = {} | ReactNodeArray;
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

// children definition in React.Component, I’ve deleted other property definition
class Component<P, S> {
        // React.Props<T> is now deprecated, which means that the `children`
        // property is not available on `P` by default, even though you can
        // always pass children as variadic arguments to `createElement`.
        // In the future, if we can define its call signature conditionally
        // on the existence of `children` in `P`, then we should remove this.
        readonly props: Readonly<P> & Readonly<{ children?: ReactNode }>;
}

// my custom component Props definition
interface Props {
    children: View[];
}

因此,我的组件的children定义是:

type C = View[] & ReactNode;

// which is equivalent to this C2
type C2 = (View[] & ReactChild) | (View[] & ReactFragment) | (View[] & ReactPortal) | (View[] & boolean) | (View[] & null) | (View[] & undefined);

如果我们更深入地展开ReactFragment,我们的类型就是这个

type C3 = (View[] & ReactChild) | (View[] & {}) | (View[] & ReactNodeArray) | (View[] & ReactPortal) | (View[] & boolean) | (View[] & null) | (View[] & undefined);

以及View[] & {}的结果是什么。我在typescript playground中编写了一个简单的演示。

// Test is equivalent to View[]
type Test = View[] & {};