如何处理打字稿中的数字输入?

jam*_*mes 13 typescript reactjs

这是在 React/TypeScript 中处理常规输入字段的方式,其中value类型为字符串:

const [value, onChange] = useState<string>('');

const onChange = (e: ChangeEvent<HTMLInputElement>) {
  setValue(e.target.value);
}

return (
  <input
    value={value}
    onChange={onChange}
  />
);
Run Code Online (Sandbox Code Playgroud)

但当我的输入是数字类型时,我遇到了麻烦:

const [value, onChange] = useState<number>();

const onChange = (e: ChangeEvent<HTMLInputElement>) {
  // type error
  setValue(e.target.value);
}

return (
  <input
    type="number"
    value={value}
    onChange={onChange}
  />
);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,值是数字类型,输入是数字类型(因此假设e.target.value应该始终是数字类型。但是根据打字稿,event.target.value它始终是字符串。我可以将其转换为数字,即。

const onChange = (e: ChangeEvent<HTMLInputElement>) {
  setValue(Number(e.target.value));
}
Run Code Online (Sandbox Code Playgroud)

但现在,如果输入某个数字并且用户将其退格以使其为空,则该值将更改为 0 - 该字段永远不会为空。

将值保留为字符串,然后在保存时将其转换为数字并不是一个可行的解决方案

我暂时做的事情是e.target.value

const onChange = (e: ChangeEvent<HTMLInputElement>) {
  setValue(e.target.value as any);
}
Run Code Online (Sandbox Code Playgroud)

效果很好,但我是否缺少一些东西来保证这种类型的安全?

Zac*_*ber 15

一般来说,您需要将变量设置为字符串,以便一切正常工作。

\n

然后,当您想将其用作数字时,请在此时将其转换。+value您可以使用类似或的方法轻松地将其转换为数字parseFloat(value)

\n

输入使用字符串类型是有原因的。这样你就可以保持打字稿提供的类型安全性。

\n

许多人建议出于各种原因完全避免数字输入:\n https://stackoverflow.blog/2022/12/26/why-the-number-input-is-the-worst-input/

\n

https://technology.blog.gov.uk/2020/02/24/why-the-gov-uk-design-system-team-changed-the-input-type-for-numbers/

\n
\n

如果您想将输入的数字数据保留为数字,您可以使用 Lo\xc3\xafc Goyet\ 的答案中的建议:

\n
const [value, onChange] = useState<number|null>(null);\n\nconst onNumberChange = (e: ChangeEvent<HTMLInputElement>) {\n  // In general, use Number.isNaN over global isNaN as isNaN will coerce the value to a number first\n  // which likely isn\'t desired\n  const value = !Number.isNaN(e.target.valueAsNumber) ? e.target.valueAsNumber : null;\n\n  setValue(value);\n}\n\nreturn (\n  <input\n    type="number"\n    value={value ?? \'\'}\n    onChange={onNumberChange}\n  />\n);\n
Run Code Online (Sandbox Code Playgroud)\n

这之所以有效,是因为数字输入的工作方式有点奇怪。如果输入有效,则将定义value扩展名 and ,否则将为空字符串。valueAsNumbervalue\'\'

\n

每当您没有值时,您可以将其与空合并运算符??number|null一起使用来应用空字符串,这样您的状态就可以代替number|string或即使number|undefined您以这种方式设置值。重要的是要使用JS 中的??不是||as !否则,您将阻止用户输入。这与OP 的值不断变化的原因类似。对于某些输入有一些潜在的意外行为,它似乎将大多数虚假值视为或。0falsy00Number()0NaN

\n

由于浏览器和反应处理输入的方式,这只适用输入。type="number"如果浏览器不支持type="number"输入,以这种方式而不是上面的方式执行此操作将会中断,在这种情况下,它会回退到type="text".

\n

如果与您相关,您还将丢失有关用户如何输入数据的信息:例如1e2vs 100

\n