如何键入在JS中创建并在TSX文件中使用的自定义React挂钩?

我有一个自定义钩子,很不幸,该钩子是用TypeScript .tsx文件中使用的纯JS编写的。

我这样称呼

const [toggleDictation,dictationResults] = useDictation()

  useEffect(() => {

    //start recognizing
    toggleDictation();

  },[]);

我在编译器中看到一条错误消息:

This expression is not callable.
  Not all constituents of type 'string | boolean | never[] | (() => Promise<void>)' are callable.
    Type 'string' has no call signatures.ts(2349)

自定义JS挂钩中的toggleDictation函数写为:


  const toggleDictation = async () => {
    try {
      if (!speechHasStarted) {
        await _startRecognizing();

        return;
      } else {
        await _stopRecognizing();
        return;
      }
    } catch (e) {
      //eslint-disable-next-line
      console.error("Error in toggleDictation,",e);
      return;
    }
  };

是否有一种方法可以强制转换或断言以正确设置函数类型以消除错误?

jlcust 回答:如何键入在JS中创建并在TSX文件中使用的自定义React挂钩?

这里真正的问题在于useDictation函数。默认情况下,即使在打字稿中,返回数组的函数也是数组而不是元组类型。

const toggleDictation = async () => { }
const useDictation = () => { // returns Array<(() => Promise<void>) | never[]>
    return [toggleDictation,[]]
}

const [tg,arr] = useDictation(); // tg is (() => Promise<void>) | never[] so uncallable

Playground Link

在ts中,您可以添加as const或显式类型注释来解决此问题:

const toggleDictation = async () => { }
const useDictation = () => { // returns Array<(() => Promise<void>) | never[]>
    return [toggleDictation,[]] as const
}

const [tg,arr] = useDictation(); // tg is now () => Promise<void>
tg() // ok

Playground Link

对于JS,我们有一些选择,如果您控制js,则可以添加jsdoc类型,它们将由TS提取:

const toggleDictation = async () => { }

/**
 * @returns {[()=> Promise<void>,string[])]}
 */
const useDictation = () => {
    return [toggleDictation,[]]
}

let [tg,d] = useDictation(); // tg is ()=> Promise<void>
tg() // ok in ts as well 


Playground Link

或者您可以添加一个声明文件,但这实际上取决于您的设置。如果为模块创建声明,那么您将无法从js获得更多推论。您可以从js文件生成一个d.ts(自3.7 PR起可用)并更正所有声明(例如返回类型useDictation

declare const useDictation : () => [()=> Promise<void>,string[]]

let [tg,d] = useDictation(); // tg is ()=> Promise<void>
tg() // ok 

Playground Link

,

键入此项不会对编译结果产生影响。 当然,如果这在普通的JS文件中有效,则我所说的是错误的,但问题似乎出在实现上,而不是缺乏输入。

本文链接:https://www.f2er.com/3146176.html

大家都在问