在 TypeScript 界面中推断 React 子 props

问题描述 投票:0回答:1

是否可以推断第一个子元素的 props 并在 TypeScript 中强制执行它们?我可以接近它,但是泛型开始失败,而且我无法推断类型。

我正在尝试将组件道具从包装器传递到具有类型安全性的第一个子组件。当对象上不存在 prop 时,TS 应该失败,否则通过。

import React, {
  Children,
  isValidElement,
  cloneElement,
  ReactNode,
} from 'react';

interface WrapperProps<C> {
  children: ReactNode;
  // how can I make typeof Button generic/inferred from the code?
  // firstChildProps: Partial<React.ComponentProps<typeof Button>>; // works with <C> removed
  firstChildProps: Partial<React.ComponentPropsWithoutRef<C>>;
}

const Wrapper: React.FC<WrapperProps<typeof Button>> = ({
  children,
  firstChildProps,
}) => {
  const firstChild = Children.toArray(children)[0];
  if (isValidElement(firstChild)) {
    // Clone the first child element and pass the firstChildProps to it
    return cloneElement(firstChild, { ...firstChildProps });
  } else {
    return <>{children}</>;
  }
};

interface ButtonProps {
  disabled: boolean;
  children: ReactNode;
}

const Button: React.FC<ButtonProps> = ({ disabled, children }) => {
  return <button disabled={disabled}>{children}</button>;
};

const Example = () => {
  return (
    <>
      {/* Passes type check because disabled exists on Button */}
      <Wrapper firstChildProps={{ disabled: false }}>
        <Button disabled={true}>Ok</Button>
      </Wrapper>
      {/* Fails type check because cheese does not exist on Button */}
      <Wrapper firstChildProps={{ cheese: true }}>
        <Button disabled={true}>Ok</Button>
      </Wrapper>
    </>
  );
};

这是一个几乎可以使用的TS Playground

javascript reactjs typescript recursion
1个回答
1
投票

您只需要向

WrapperProps<C>
添加通用约束 - 与
ComponentPropsWithoutRef<C>
具有的相同 - 即
ElementType

interface WrapperProps<C extends React.ElementType> {
  children: ReactNode;
  firstChildProps: Partial<React.ComponentPropsWithoutRef<C>>;
}
© www.soinside.com 2019 - 2024. All rights reserved.