Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何正确推断反应道具从作为道具与通用重载_Reactjs_Typescript_Generics - Fatal编程技术网

Reactjs 如何正确推断反应道具从作为道具与通用重载

Reactjs 如何正确推断反应道具从作为道具与通用重载,reactjs,typescript,generics,Reactjs,Typescript,Generics,我试图制作一个通用组件,它可以根据作为道具推断道具类型 我发现以下类型对于{as?:keyof JSX.intrinsiceelements}来说可以正常工作: import React from 'react'; interface Comp<TComponentProps extends {}> { (props: TComponentProps & { as?: undefined }): React.ReactElement | null; <

我试图制作一个通用组件,它可以根据
作为
道具推断道具类型

我发现以下类型对于
{as?:keyof JSX.intrinsiceelements}
来说可以正常工作:

import React from 'react';

interface Comp<TComponentProps extends {}> {
  (props: TComponentProps & { as?: undefined }): React.ReactElement | null;

  <
    TProps extends { as: keyof JSX.IntrinsicElements },
    P = TProps extends { as: infer C }
      ? C extends keyof JSX.IntrinsicElements
        ? JSX.IntrinsicElements[C] & TComponentProps
        : TComponentProps
      : TComponentProps
  >(
    props: TProps & P,
  ): React.ReactElement | null;
}

declare const A: Comp<{}>;
declare const B: Comp<{ test: boolean }>;
declare const C: React.FunctionComponent<{ fn: boolean }>;
declare const D: React.ComponentClass<{ cls: boolean }>;

<A />; // valid
<B />; // invalid, test is missing
<B test />; // valid
<A as="img" src={10} />; // invalid, src cannot be a number
<A as="img" src="" />; // valid
/* 

<A as={B} />; // invalid, test is missing
<A as={B} test />; // valid
<A as={C} />; // invalid, fn is missing
<A as={C} fn />; // valid
<A as={D} />; // invalid, cls is missing
<A as={D} cls />; // valid

*/

我没有得到预期的结果,但所有行都通过了类型检查

我尝试了多种可能的解决方案,例如:

import React from 'react';

interface Comp<TComponentProps extends {}> {
  <
    TProps extends {
      as?: keyof JSX.IntrinsicElements;
    },
    P = TProps extends { as?: infer C }
      ? C extends undefined | unknown
        ? {}
        : C extends keyof JSX.IntrinsicElements
        ? JSX.IntrinsicElements[C]
        : {}
      : {}
  >(
    props: TProps & TComponentProps & P,
  ): React.ReactElement | null;
  <
    TProps extends {
      as?: React.JSXElementConstructor<any>;
    },
    P = TProps extends { as: React.JSXElementConstructor<infer P> } ? P : {}
  >(
    props: TProps & TComponentProps & P,
  ): React.ReactElement | null;
}

declare const A: Comp<{}>;
declare const B: Comp<{ test: boolean }>;
declare const C: React.FunctionComponent<{ fn: boolean }>;
declare const D: React.ComponentClass<{ cls: boolean }>;

<A />; // valid
<B />; // invalid, test is missing
<B test />; // valid
<A as="img" src={10} />; // invalid, src cannot be a number
<A as="img" src="" />; // valid
<A as={B} />; // invalid, test is missing
<A as={B} test />; // valid
<A as={C} />; // invalid, fn is missing
<A as={C} fn />; // valid
<A as={D} />; // invalid, cls is missing
<A as={D} cls />; // valid
从“React”导入React;
接口组件{
<
TProps扩展{
as?:JSX.intrinsiceelements的键;
},
P=TProps扩展{as?:推断C}
?C扩展未定义|未知
? {}
:C扩展JSX.intrinsiceelements的键
?JSX.本质元素[C]
: {}
: {}
>(
道具:TProps&t组件道具&P,
):React.ReactElement | null;
<
TProps扩展{
as?:React.JSXElementConstructor


但是运气不好。有人能给我指出正确的打字方向吗?

好的,我通过以下打字解决了这个问题:


type HTMLELProps<
  TElement extends keyof JSX.IntrinsicElements,
  TComponentProps extends {}
> = { as: TElement } & JSX.IntrinsicElements[TElement] &
  TComponentProps &
  StyleProps &
  React.RefAttributes<any>;


export interface Component<TComponentProps extends {}> {
  displayName?: string;

  // as component (as component type)
  <P>(
    props: { as: React.ComponentType<P> } & P &
      TComponentProps &
      StyleProps &
      React.RefAttributes<any>,
  ): React.ReactElement | null;

  // HTML (as="a")
  (props: HTMLELProps<'a', TComponentProps>): React.ReactElement | null;
  (props: HTMLELProps<'abbr', TComponentProps>): React.ReactElement | null;
  // ... rest 

  // without as prop
  (props: TComponentProps & StyleProps): React.ReactElement | null;
}

键入HTMLELProps<
TElement扩展了JSX.intrinsiceElements的功能,
TComponentProps扩展了{}
>={as:TElement}&JSX.intrinsiceelements[TElement]&
t组件支柱&
样式道具&
React.RefAttributes;
导出接口组件{
displayName?:字符串;
//作为组件(作为组件类型)

( 支柱:{as:React.ComponentType

}&P& t组件支柱& 样式道具& React.RefAttributes, ):React.ReactElement | null; //HTML(as=“a”) (props:htmleprops):React.ReactElement | null; (props:htmleprops):React.ReactElement | null; //……休息 //没有支柱 (props:TComponentProps和StyleProps):React.ReactElement | null; }

基本上,问题是typescript很难根据泛型约束推断道具。现在,即使在Visual Studio代码中使用autocomplete,它也能正常工作。问题是,类型现在有点慢。我不知道为什么,我希望您能提供帮助


type HTMLELProps<
  TElement extends keyof JSX.IntrinsicElements,
  TComponentProps extends {}
> = { as: TElement } & JSX.IntrinsicElements[TElement] &
  TComponentProps &
  StyleProps &
  React.RefAttributes<any>;


export interface Component<TComponentProps extends {}> {
  displayName?: string;

  // as component (as component type)
  <P>(
    props: { as: React.ComponentType<P> } & P &
      TComponentProps &
      StyleProps &
      React.RefAttributes<any>,
  ): React.ReactElement | null;

  // HTML (as="a")
  (props: HTMLELProps<'a', TComponentProps>): React.ReactElement | null;
  (props: HTMLELProps<'abbr', TComponentProps>): React.ReactElement | null;
  // ... rest 

  // without as prop
  (props: TComponentProps & StyleProps): React.ReactElement | null;
}