对于反应+类型脚本变量:强制组件的属性中的某些属性属性、变量、脚本、组件

2023-09-03 13:32:42 作者:小爷有小爷的独特范

我希望有一个变量(实际上是函数参数,但我简化了问题),它可以包含Reaction组件,该组件必须在其属性中包含aNumber: number

我未成功的尝试是:

function MyComp(props: { aNumber: number, aString: string }) {
    return <>{props.aNumber} {props.aString}</>;
}

let f2: FunctionComponent<{ aNumber: number }> = MyComp;
PLC块中的结构变量如何组态能在WinCC中使用

给我错误:

Type '(props: { aNumber: number; aString: string; }) => Element' is not assignable to type 'FunctionComponent<{ aNumber: number; }>'.
  Types of parameters 'props' and 'props' are incompatible.
    Property 'aString' is missing in type 'PropsWithChildren<{ aNumber: number; }>' but required in type '{ aNumber: number; aString: string; }'.ts(2322)

FunctionComponent在Reaction中定义为:

    interface FunctionComponent<P = {}> {
        (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
        propTypes?: WeakValidationMap<P>;
        contextTypes?: ValidationMap<any>;
        defaultProps?: Partial<P>;
        displayName?: string;
    }

我不明白这个错误。如果我定义了一个var w/a约束aNumber,并且为它分配了一个更丰富的元素=>;,为什么它不满意呢?为什么它会抱怨这些更丰富的属性?

当然,以下是可行的:

let f1: FunctionComponent<any> = MyComp;

通常,当我在TS中尝试高级类型构造时,在经历了许多头痛之后,我终于让它工作了。这一次它似乎不是很高级,但我没能弄明白。

提前表示感谢。

推荐答案

问题是,反应组件是函数,而函数是反向变量,这意味着如果需要具有T类型参数的函数,则它可以满足于比T更宽类型的函数,但不能满足较窄类型的函数。这与纯对象相反,后者是co变体,即将接受较窄的类型,但不接受较宽的类型。

您可以在没有任何反应代码的情况下看到相同的结果

function MyFunc(props:{a: number, b: string}){return}

let func2: (props:{a:number})=>void = MyFunc 
//   ^-- error because MyFunc is narrower than typeof func2

从调用您的函数/Reaction组件的消费者的角度来看,这是一种直观的方式。在他们期望调用typeof f2的函数的情况下,他们预计只需要传递aNumber的道具,但是通过将更窄的函数分配给f2,他们现在还需要传递aString,这是他们没有预料到的。

出于可以理解的原因,这个问题经常出现在我们的反应中。假设您有一个<Button>组件和一个<FancyButton>组件,前者需要一个道具,后者需要多个道具。人们不禁会想,如果我需要一个旧的<Button>,那么一个<FancyButton>就可以了。这听起来像是简单的继承。但如果你再想一想,就会发现有一个错误。如果我是一个组件,希望需要插入<Button>作为我的子级之一,这意味着我只需要向它传递一个道具。如果我现在换入<FancyButton>,组件现在需要一些我不希望提供道具。

直观的观点是,您不仅仅是显示<Button>组件--在这种情况下,您可能根本不关心<FancyButton>具有更多的&q;幻想&q;这一事实。您实际上需要向组件提供输入--道具,因此范围较小的输入将需要您(父组件)提供更多。

当然,相同的逻辑对于所有函数通常都是正确的,但我猜这往往会在Reaction中更频繁地出现,因为我们倾向于将组件视为要显示的对象。

这里有一个关于这个问题的更广泛的答案(一开始很棘手!):Difference between covariant and contravariant positions in Typescript