Home > OS >  Typescript: Argument of type '(i: string[]) => any[]' is not assignable to parameter of
Typescript: Argument of type '(i: string[]) => any[]' is not assignable to parameter of

Time:09-20

In my project, I am trying to add multiple emails as a chip. But I am facing a problem here, first time, when I paste multiple email values it gets inserted into the field, but second time when I copy some other values and paste them into the field, it replaces the previous values. to solve this added a line "setItem((i: string[]) => [...i, ...toBeAdded]);" inside "handlePaste". but this leads to another issue "Typescript: Argument of type '(i: string[]) => any[]' is not assignable to parameter of type 'string[]'."


type Props = {
  LabelName?: string;
  optional?: string;
  tooltip?: string;
  placeholder?: string;
  className?: string;
  upload?: boolean;
  items?: any;
  setItem: (items: string[]) => void;
};
const TagActions = (props: Props) => {
  // const [items, setItem] = useState<string[]>([]);
  const [value, setValue] = useState("");
  const [error, setError] = useState("");
  const divRef = useRef<HTMLDivElement>(null);
  const [flag, setFlag] = useState(false);

  const {
    LabelName,
    optional,
    tooltip,
    placeholder,
    className,
    upload,
    items,
    setItem,
  } = props;

  const handleDelete = (item: any) => {
    const result = items.filter((i: any) => i !== item);
    setItem(result);
  };

  const handleItemEdit = (item: any) => {
    const result = items.filter((i: any) => i !== item);
    setItem(result);
    setValue(item);
  };

  const handleKeyDown = (evt: any) => {
    if (["Enter", "Tab", ","].includes(evt.key)) {
      evt.preventDefault();

      const test = value.trim();

      if (test && isValid(test)) {
        items.push(test);
        setValue("");
      }
    }
  };

  const isValid = (email: any) => {
    let error = null;

    if (isInList(email)) {
      error = `${email} has already been added.`;
    }

    if (!validator.isEmail(email)) {
      setFlag(true);
    }

    if (error) {
      setError(error);

      return false;
    }

    return true;
  };

  const isInList = (email: any) => {
    return items.includes(email);
  };

  const handleChange = (evt: any) => {
    setValue(evt.target.value);
  };

  const handlePaste = (evt: any) => {
    evt.preventDefault();

    const paste = evt.clipboardData.getData("text");
    const emails = paste.match(/[\w\d\\.-] @[\w\d\\.-] \.[\w\d\\.-] /g);

    if (emails) {
      const toBeAdded = emails.filter((email: any) => !isInList(email));

      console.log("items inside", items);
      console.log("toBeAdded", toBeAdded);

      
      setItem((i: string[]) => [...i, ...toBeAdded]);
      console.log("items after", items);
    }
  };

  return (
    <>
      <div className="formSection">
        {LabelName && (
          <div className={`control-label ${styles.label}`}>
            <label>
              <span className={styles.alignLeft}>
                <span className={styles.labelText}>{LabelName}</span>
              </span>
            </label>

            <span className={styles.alignRight}>
              {upload && (
                <label htmlFor="uploadCSV">
                  <span className={styles.upload}>Upload CSV</span>
                </label>
              )}

              {optional && <span className={styles.light}>Optional</span>}

              {tooltip && (
                <span className={styles.tooltip_ic} title={tooltip}>
                  <FontAwesomeIcon icon={faCircleQuestion} size="xs" />
                </span>
              )}
            </span>
          </div>
        )}
        <input
          type="file"
          accept=".csv"
          style={{ display: "none" }}
          id="uploadCSV"
        />
        <div className={styles.inputGroup}>
          <TextField
            className={` textfield-emailchip test ${className}`}
            InputProps={{
              startAdornment: items.map(
                (
                  item:
                    | boolean
                    | Key
                    | ReactElement<any, string | JSXElementConstructor<any>>
                    | ReactFragment
                    | null
                    | undefined
                    | any
                    | string
                ) => (
                  <Chip
                    className={
                      !validator.isEmail(item)
                        ? styles.chipTagError
                        : styles.chipTag
                    }
                    key={item}
                    tabIndex={-1}
                    label={item}
                    onDelete={() => handleDelete(item)}
                    onClick={() => handleItemEdit(item)}
                    deleteIcon={<FontAwesomeIcon icon={faXmark} size="xs" />}
                  />
                )
              ),
            }}
            ref={divRef}
            value={value}
            placeholder={placeholder}
            onKeyDown={(e) => handleKeyDown(e)}
            onChange={(e) => handleChange(e)}
            onPaste={(e) => handlePaste(e)}
          />
        </div>

        {error && <p className="error">{error}</p>}
      </div>
    </>
  );
};

export default TagActions;


Please give me a solution to fix this problem.

CodePudding user response:

setItem is defined as having the type (items: string[]) => void. This definition means it is a function that accepts an array of strings, for example setItem(['a', 'b', 'c']) would be a valid invocation of a function with this type.

However, in the code setItem is then called differently, like this:

setItem((i: string[]) => [...i, ...toBeAdded]);

The argument (i: string[]) => [...i, ...toBeAdded] is not an array of strings; it is itself another function. TypeScript is saying this code is invalid because the argument given to setItem is a function, not an array of strings.

You can either change the invocation to pass an array of strings, or change the definition to say it's supposed to accept a function, depending on which matches your true intent for the code.

  • Related