【问题标题】:Why is typescript inferring the generic type to be type ""为什么打字稿推断泛型类型是类型“”
【发布时间】:2022-01-03 19:30:50
【问题描述】:

我创建了这个名为 StateWithValidation 的 React 组件。

import { useStateWithValidation } from "./useStateWithValidation";

export const StateWithValidation = () => {
  const [username, setUserName, isValid] = useStateWithValidation(
    (value: string) => value.length > 5,
    ""
  );

  return (
    <div>
      <div>Valid: {isValid.toString()}</div>
      <input
        type="text"
        value={username}
        onChange={(e) => setUserName(e.target.value)}
      />
    </div>
  );
};

我有一个通用的自定义钩子,它验证和处理用户输入更改。

import { useCallback, useState } from "react";

type useStateValidationFn = <U>(
  validationFunc: (value: U) => boolean,
  initialState: U
) => [U, (nextState: U) => void, boolean];

export const useStateWithValidation: useStateValidationFn = (
  validationFunc,
  initialValue
) => {
  const [state, setState] = useState(initialValue);
  const [isValid, setIsValid] = useState(() => validationFunc(state));

  const onChange = useCallback(
    (nextState) => {
      setState(nextState);
      setIsValid(validationFunc(nextState));
    },
    [validationFunc]
  );

  return [state, onChange, isValid];
};

为什么我在React组件中输入的时候,泛型类型的值是""而不是字符串。

【问题讨论】:

  • 因为你的初始状态是 ""... add 使用你的钩子时,
  • 为什么不是从我传递的方法推断出来的 (value: string) => value.length > 5 ?
  • 这是一个有趣的问题;我很惊讶这里有一个字面的上下文。可能与ms/TS#43804 相关,也可能不相关。研究尚未发现任何确定的结果。
  • 是的,我无法找到答案;一般而言,如果您有T extends string,那么您可以期望推断出像"" 这样的字符串文字类型,但是没有约束的T 通常会推断出像string 这样的扩展类型。 minimal reproducible example 可能是 this code。有人(你?)可能想打开GitHub issue 询问发生了什么事。我会继续寻找一点,但我并不乐观。

标签: reactjs typescript


【解决方案1】:

尝试如下改变

const [username, setUserName, isValid] = useStateWithValidation(
    (value: string) => value.length > 5,
    new String()
  );

【讨论】:

  • 使用String as a constructor 几乎从来都不是一个好主意;你可以改写String(),或者"" as string。另请注意,问题似乎是“为什么会发生这种情况”而不是“我该如何解决它”
  • 这将起作用并且类型将被推断为字符串而不是字符串。但是我们会得到一个错误,即 只接受 string 类型的 value 而不是 String。我们将不得不这样做 .
  • @jcalz 好吧,我真的不想解决它。可以通过键入 useStateWithValidation( (value: string) => value.length > 5, "" ); 轻松修复它。我不明白为什么会这样。
  • @Dusan 我认为我们在同一页上?你不是在问如何解决它(这很容易),而是为什么它会发生(这对我来说并不容易回答)
猜你喜欢
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 2022-09-29
  • 2020-03-22
  • 2020-12-17
  • 2021-05-06
  • 1970-01-01
  • 2021-11-26
相关资源
最近更新 更多