TypeScript 在将函数导入另一个文件后更改函数的类型定义

TypeScript changing type definition of a function after importing it to another file

我有一个名为 useDropdownSelection 的自定义挂钩。这很简单。这是代码:

import { useState } from 'react'

export const useDropdownSelection = (initialValue: string) => {
  const [selectedOption, setSelectedOption] = useState<string>(initialValue)

  const handleClick = (event: React.MouseEvent<HTMLLIElement>) => {
    const target = event.target as HTMLElement
    setSelectedOption(target.innerText)
  }

  return [selectedOption, handleClick]
}

如你所见,handleClick函数的类型是(event: React.MouseEvent<HTMLLIElement>) => void

但是当我将它导入我的 index.tsx 时,handleClick 函数由于某种原因变成了 string | ((event: MouseEvent<HTMLLIElement, MouseEvent>) => void)

类型
const [selectedDropdownOption, handleDropdownClick] = useDropdownSelection('Most upvotes') // const handleDropdownClick: string | ((event: MouseEvent<HTMLLIElement, MouseEvent>) => void). WHY?

为什么会这样?

我认为这与我返回数组有关?

If you are returning an array in your Custom Hook, you will want to avoid type inference as TypeScript will infer a union type (when you actually want different types in each position of the array).

如果你想避免联合类型,你需要做的是使用 const 断言:

return [selectedOption, handleClick] as const;

现在 selectedOptionhandleClick 将分别保留它们的类型。

文档:https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/hooks/#custom-hooks

因为你没有指定useDropdownSelection每个索引要return特定类型的数组,所以TS假设每个索引可能包含回调和字符串值。 检查下面的例子:

const f = (s: string) => {
  const n: number = 5;
  return [s, n];
}
const result = f('s');

result(string | number)[] 类型。要明确通知它将成为 [string, number] 你必须像下面这样实现它:

const f = (s: string): [string, number] => {
  const n: number = 5;
  return [s, n];
}
const result = f('s'); // type is [string, number]

上面提供的语法类似于 useState 实现的语法。

因此在您的示例中明确键入 return 钩子的值:

export const useDropdownSelection = (initialValue: string): [string, (event: MouseEvent<HTMLLIElement, MouseEvent>) => void] => {...}