typescript React组件中的可选通用部件

sdnqo3pr  于 2023-03-13  发布在  TypeScript
关注(0)|答案(2)|浏览(120)

下面的代码有两个问题。

interface MyForm {
  age: number;
  email: string;
  name: string;
}

function Form<
  T,
  ComponentProps extends {
    name: string;
    onChange: (event: React.ChangeEvent) => void;
  }
>(
  props: {
    component:
      | React.ComponentClass<ComponentProps>
      | React.ComponentType<ComponentProps>;
    name: keyof T;
  } & Omit<ComponentProps, "name" | "onChange">
) {
  const { component: Component, name, ...rest } = props;

  const handleChange = () => {
    //
  };

  return <Component {...(rest as any)} name={name} onChange={handleChange} />;
}

function Component(props: {
  name: string;
  onChange: (event: React.ChangeEvent) => void;
  color: "blue" | "yellow";
}) {
  const { color, name, onChange } = props;
  return <input name={name} onChange={onChange} style={{color}} />;
}

function App() {
  return (
    <>
      {/* in this code, the name is not checked */}
      <Form color="blue" component={Component} name="something" />
      {/* in this code, the name is checked, but I must define all generics */}
      <Form<MyForm, React.ComponentProps<typeof Component>>
        color="yellow"
        component={Component}
        name="name"
      />
      {/* this doesn't work */}
      <Form<MyForm> color="blue" component={Component} name="email" />
    </>
  );
}

首先,我想像<Form<MyForm> color="blue" component={Component} name="email" />这样调用Form组件,而不是定义第二个泛型。在一个复杂的组件中,我有更多的属性和泛型,我不想强迫其他程序员定义所有的泛型,只是因为我希望name必须匹配MyForm中的键。这就是目标。name必须通过TypeScript检查,并且必须是MyForm的keyof,我知道我可以使用可选泛型并定义默认类型,但这违反了逻辑,然后我在调用Form时无法传递color,并且我无法定义颜色是必需的,因为逻辑是,component必须有nameonChange属性,剩下的我不关心,把剩下的传递给组件就行了。
第二,我不能去掉{...(rest as any)}中的any。我不知道,为什么我只使用{...rest}时会得到一个错误。

um6iljoc

um6iljoc1#

看起来您在第一个问题中要求的是让<Form>组件的用户能够指定 * 一些 * 泛型参数(例如<Form<MyFormInterface> />),并让typescript仍然推断其余参数(例如传递给component属性的组件属性)。
不幸的是,目前还不支持类型推断-类型推断是一个全有或全无的命题-要么typescript推断所有内容,要么用户指定所有内容。有an extremely popular github issue asking for this exact feature。另请参见this answer以获得更一般的解释。

xmjla07d

xmjla07d2#

有一种方法可以定义和导出函数重载

export function a<A>(value: A, value2: string) :void
export function a<A,T>(value: A, value2:T) : void
export function a<A,T>(value: A, value2:T) {
  console.log(value, value2)
}
//throw error
a<string>("", 3)
//good
a<string>("","")
//throw error
a<string, number>("","")
//good
a<string, number>("",2)

相关问题