反应打字稿-将道具传递到挂钩之间的类型错误

I have created this codesandbox replicating my issue

  • 1) I first created the component, (for styling and track if the input has content or not.
  • 2) Everything works, but as need to add more forms to the project, i thought, damn maybe i could also created an useInput hook to just manage the value update instead of having to add onChange: {e => {setSomething(e.target.value)}} all the time.

So i created these useInput, but i got this annoying red linter errors. Its probably some basic type issue, but i can figure it out how to get rid of this issue. without any type solutions ? Thanks in advance

Error screenshot and chunk of code below, but better test in the sandbox

enter image description here

#useInput.tsx

import { useState, ChangeEvent } from "react";

export type onChangeType = (event: ChangeEvent<HTMLInputElement>) => void;
const useInput = (initialValue = "") => {
  const [value, setValue] = useState(initialValue);

  const reset = () => setValue("");

  const onChange: onChangeType = e => {
    setValue(e.target.value);
  };

  return [value, onChange, reset];
};

export default useInput;

#Input.tsx

import React, { useState, ChangeEvent } from "react";
import styled, { css } from "styled-components";

import onChangeType from "./hooks/useInput";

interface iLabelProps {
  hasContent: boolean;
}

const hasContentCSS = () => css`
  border: 5px solid royalblue;
`;

const Label = styled.label<iLabelProps>```

interface iInput {
  readonly type?: string;
  readonly name: string;
  readonly label: string;
  value?: string | number | string[] | null;
  defaultValue?: string | number | string[] | null;
  readonly onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
}

export const Input = ({
  name = "email",
  label,
  value = null,
  defaultValue = null,
  onChange = null
}: iInput) => {
  const [hasContent, setHasContent] = useState(!!defaultValue);

  const onBlur = value => {
    setHasContent(value.length > 0);
  };

  return (
    <Label hasContent={hasContent}>
      <input
        type="text"
        name={name}
        {...defaultValue && { defaultValue: defaultValue }}
        {...!defaultValue && { value: value ? value : "" }}
        {...onChange && { onChange: onChange }}
        onBlur={e => onBlur(e.target.value)}
      />
      <span>{label}</span>
    </Label>
  );
};

评论
Avery
Avery

The problem came from the incorrectly inferred type of the returned value from the useInput hook. TS think that the type is (string | onChangeType)[]. That means that string or onChangeType can be at any position in the array, while you have very fixed order.

要解决此问题,您需要提供一些帮助,然后像这样强制转换返回的数组

return [value, onChange, reset] as [string, onChangeType, () => void];

或明确指定useInput函数的返回类型

const useInput = (initialValue = ""): [string, onChangeType, () => void] => {...}
点赞
评论