reactjs 如何根据函数或函数参数键入开关案例?

im9ewurl  于 2023-08-04  发布在  React
关注(0)|答案(1)|浏览(81)

我有一个函数,它返回一个input元素及其相应的属性,该属性基于接收onChange事件的函数。该功能在组件 prop 中被接收。问题是,我无法键入函数接收到HTMLInputElement、HTMLSelectElement或HTMLTextareaElement的ChangeEvent的情况。

type OptionsProps = {
    description: string;
    value: string;
};

type SelectProps = {
    handleChange: ({ target }: React.ChangeEvent<HTMLSelectElement>) => void;
    value: string;
    options: OptionsProps;
};

type TextareaProps = {
    handleChange: ({ target }: React.ChangeEvent<HTMLTextAreaElement>) => void;
    cols?: number;
    rows?: number;
};

type InputProps = {
    handleChange: ({ target }: React.ChangeEvent<HTMLInputElement>) => void;
} & (InputNumberProps | InputTextProps | InputFileProps);

type Props = {
    title: string;
    name: string;
    htmlFor: string;
} & (InputProps | TextareaProps | SelectProps);

export const ModalFormDivider = (props: Props) => {
    const { title, name, htmlFor, handleChange} = props;

    const determineElement = () => {
        switch (handleChange) {
            case (({ target }: React.ChangeEvent<HTMLSelectElement>) => void): {...Do something}
case (({ target }: React.ChangeEvent<HTMLTextareaElement>) => void): {...Do other thing}
case (({ target }: React.ChangeEvent<HTMLSelectElement>) => void): {...Do whatever}
        }
    };
}

字符串
我试着把编辑器说handleChange是(({ target }:例如,React.ChangeEvent)=> void),但它不起作用。

bprjcwpo

bprjcwpo1#

首先让我们看看switch语句的定义。

switch (expression_or_value) {
  case comparison_expression_or_value1:
    statements
  case comparison_expression_or_value2:
    statements
  // …
  case comparison_expression_or_valueN:
    statements
  default:
    statements
}

字符串
switch语句计算expression/value,然后将计算结果与case子句的expression/value进行比较。与初始expression/value匹配的case子句的代码块将最终成为结果。
在您的示例中,您将type作为case值传递,这将不起作用,因为类型不是有效的expression/value
下面是你正在做的事情的分解:

type FNType1 = ({ target }: { target: Record<string, any> }) => void
type FNType2 = ({ target }: { target: Record<string, any> }) => void

const fn: FNType1 = ({ target }) => {}
const fn2: FNType2 = ({ target }) => {}

const checkFnType = (f: Function) => {
  switch (typeof f) {
    case FNType1:
      console.log('x')
      break; 

    case FNType2:
      console.log('x2')
      break; 
    default:
      break;
  }
}


这实际上应该在IDE中抛出一个错误,如:

'FNType1' only refers to a type, but is being used as a value here.


如果你真的想这样做,你可以在switch语句中比较函数,但这需要函数调用签名不同。

type FNType1 = ({ target }: { target: Record<string, any> }) => void
type FNType2 = ({ target }: { target: Record<string, any> }) => void

const fn: FNType1 = ({ target }) => {}
const fn2: FNType2 = ({ target }) => {}

const checkFn = (f: Function) => {
  switch (f) {
    case fn:
      console.log('function 1')
      break;
    
    case fn2:
      console.log('function 2')
      break;  
    default:
      break;
  }
}

checkFn(fn); // function 1
checkFn(fn2); // function 2


我认为你真正想做的是使用一个generic,它将帮助你在ModalFormDivider组件用法中正确地键入handleChange函数。您还需要添加一个type prop来选择要返回的元素。这更符合(我认为)你正在努力做的事情。

type AdditionalProps<T> = T extends HTMLTextAreaElement
  ? TextAreaProps
  : T extends HTMLSelectElement
  ? SelectProps
  : T extends HTMLInputElement
  ? InputProps
  : {};

interface ModalFormDividerProps<T> {
  title: string;
  name: string;
  htmlFor: string;
  type: "select" | "input" | "textarea";
  handleChange: (args: React.ChangeEvent<T>) => void;
}
const ModalFormDivider = <T extends Record<string, any>>({
  title,
  name,
  htmlFor,
  handleChange,
  type,
  ...rest
}: ModalFormDividerProps<T> & AdditionalProps<T>) => {

  console.log(title, name, htmlFor, handleChange, rest);

  switch (type) {
    case "input":
      return <TextField {...rest} />;
    case "select":
      const { value, options } = (rest as unknown) as SelectProps;
      return (
        <Select value={value}>
          {options.map((option) => (
            <MenuItem value={option}>{option}</MenuItem>
          ))}
        </Select>
      );
    case "textarea":
      return <TextField {...rest} multiline />;

    default:
      console.error("Unexpected component type", type);
      return null;
  }
};

的字符串
希望这对你有帮助!

相关问题