网站搜索

reactjs - 只能调用用花括号导出/解构的函数,而不能用方括号


在一个基本的 React 自定义 Hook 中,唯一的区别是返回 [ ] 还是 { }:

const useCustomHookSquare= () => {
  const [state, setState] = useState<Type>(initialState);

  return [state, storeBounceBox];
}

const useCustomHookCurly= () => {
  const [state, setState] = useState<Type>(initialState);

  return {state, storeBounceBox};
}

这个有效:

const {state, setState} = useCustomHookCurly();
// or even
const {setState} = useCustomHookCurly();

但是用方括号进行完全相同的解构,在调用 setState 函数(或以这种方式导出的任何其他函数)时会给我一个 TypeScript 错误:

const [state, setState] = useCustomHookSquare();
setState(someState); // "This expression is not callable. Type has no call signatures".

我感觉这里我遗漏了一些基本的 JavaScript 概念。为什么 {} 版本允许我调用函数,而 [] 版本却不行?

答案#1

因为你的 useCustomHookSquare 钩子没有返回类型信息,TypeScript 推断它返回一个包含两种不同类型的数组。但数组中可能的两种类型并非都是函数,因此会出现类型错误,因为其中一个可能的值不可调用。

const useHook = () => {
  return ["item", () => true]
}

// The inferred value of useHook is now
//
// (string | (() => boolean))[]
//
// So when calling `fn`, TypeScript doesn't know if it will be a string or a function
const [item, fn] = useHook()

//This expression is not callable.
//  Not all constituents of type 'string | (() => boolean)' are callable.
//    Type 'string' has no call signatures.
fn()

为你的 useCustomHookSquare 函数添加一些返回类型以解决问题。这是我修复后的示例。

const useHook = (): [string, () => true] => {
  return ["item", () => true]
}

TypeScript 现在理解返回的数组中只有 2 个项目,并且这些项目的类型应该始终相同。

答案#2

默认情况下,TypeScript 会为数组分配一个更广泛的类型。因此,如果你有:

const arr = ["str", 5];

该类型将是 (string | number)[] 的数组,而不是 [string, number] 的元组。

要将其转换为元组,请使用 as const:

const useCustomHookSquare= () => {
  const [state, setState] = React.useState<string>();

  return [state, setState] as const;
}