最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - This expression is not callable when destructuring an array of React hooks in TypeScript - Stack Overflow

programmeradmin0浏览0评论

In my React TS ponent I have a bunch of fields, contrived example below, that check a specific condition, and if it is not met, set the specific field error to true, to be reflected and the ponent DOM (and thus not submit) However when I have the code below it throws an expression not callable on the setErr function.

const App = () => {
  const [name, setName] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [nameError, setNameError] = React.useState(false);
  const [emailError, setEmailError] = React.useState(false);
  return (
    <div className="App">
      <input
        type="text"
        value={name}
        style={{
          border: `1 px solid ${nameError ? "red" : "black"}`
        }}
        onChange={e => {
          setName(e.target.value);
        }}
      />
      <input
        type="text"
        value={email}
        onChange={e => {
          setEmail(e.target.value);
        }}
        style={{
          border: `1 px solid ${emailError ? "red" : "black"}`
        }}
      />
      <button
        onClick={() => {
          const errors = [
            [setNameError, name.length],
            [setEmailError, email.length]
          ];

          let canSubmit = true;
          errors.forEach(validation => {
            const [setErr, condition] = validation;
            console.log(!condition);
            if (!condition) {
              canSubmit = false;
              setErr(true); // <---- ERROR HERE
            }
          });

          if (canSubmit) { /* submit the form */ } 
        }}
      >
        submit
      </button>
    </div>
  );
};

This only errors in TypeScript as it works fine in vanilla/jsx. And doesn't pile in some build systems.

Full error is:

This expression is not callable.
  Not all constituents of type 'string | number | boolean | Dispatch<SetStateAction<boolean>>' are callable.
    Type 'string' has no call signatures.

I am especially confused why it thinks setErr is of type string, when it should be equal to the setNameError function destructured from useState.

In my React TS ponent I have a bunch of fields, contrived example below, that check a specific condition, and if it is not met, set the specific field error to true, to be reflected and the ponent DOM (and thus not submit) However when I have the code below it throws an expression not callable on the setErr function.

const App = () => {
  const [name, setName] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [nameError, setNameError] = React.useState(false);
  const [emailError, setEmailError] = React.useState(false);
  return (
    <div className="App">
      <input
        type="text"
        value={name}
        style={{
          border: `1 px solid ${nameError ? "red" : "black"}`
        }}
        onChange={e => {
          setName(e.target.value);
        }}
      />
      <input
        type="text"
        value={email}
        onChange={e => {
          setEmail(e.target.value);
        }}
        style={{
          border: `1 px solid ${emailError ? "red" : "black"}`
        }}
      />
      <button
        onClick={() => {
          const errors = [
            [setNameError, name.length],
            [setEmailError, email.length]
          ];

          let canSubmit = true;
          errors.forEach(validation => {
            const [setErr, condition] = validation;
            console.log(!condition);
            if (!condition) {
              canSubmit = false;
              setErr(true); // <---- ERROR HERE
            }
          });

          if (canSubmit) { /* submit the form */ } 
        }}
      >
        submit
      </button>
    </div>
  );
};

This only errors in TypeScript as it works fine in vanilla/jsx. And doesn't pile in some build systems.

Full error is:

This expression is not callable.
  Not all constituents of type 'string | number | boolean | Dispatch<SetStateAction<boolean>>' are callable.
    Type 'string' has no call signatures.

I am especially confused why it thinks setErr is of type string, when it should be equal to the setNameError function destructured from useState.

Share Improve this question edited Apr 10, 2020 at 3:40 Afs35mm asked Apr 9, 2020 at 23:46 Afs35mmAfs35mm 6493 gold badges11 silver badges25 bronze badges 3
  • What's the inferred type of error ? – Jonas Wilms Commented Apr 10, 2020 at 0:14
  • errors or error? @JonasWilms – Afs35mm Commented Apr 10, 2020 at 3:40
  • I'd suggest using null as placeholder for "no value", instead of false, which is an answer to a yes/no question – Parzh from Ukraine Commented Apr 10, 2020 at 9:45
Add a ment  | 

2 Answers 2

Reset to default 9

All you need is to add as const to the errors declaration:

  const errors = [
        [setNameError, name.length],
        [setEmailError, email.length]
   ] as const;

That way, the arrays won't be typed as arrays but as tuples.

The inferred type of errors is what's shooting you down here. By your error message we can derive that const errors: (string | number | boolean | Dispatch<SetStateAction<boolean>>)[][], hence typescript infers that the array elements can be a bunch of things, some of which are not callable. Instead you could objectify it, and the types inferred will be assigned to keys, allowing you do deconstruct and call properly, i.e.

<button
  onClick={() => {
    const errors = [
      {setError:setNameError, condition:name.length},
      {setError:setEmailError, condition:email.length}
    ];

    let canSubmit = true;
    errors.forEach(validation => {
      const {setError, condition} = validation;
      console.log(!condition);
      if (!condition) {
        canSubmit = false;
        setError(true); // <---- ERROR HERE
      }
    });

    if (canSubmit) { /* submit the form */ } 
  }}
>

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论