为了更好地理解,这里有一些代码(经过简化):
发送请求的包装器
- 它在请求发送和完成时做一些常见的事情。
- 它返回请求的结果(处理程序)。
async function request (handler) {
// common stuff
try {
const result = await handler()
return result || true
}
catch (err) {
doSomethingWithError(err)
return err
}
finally {
// common stuff
}
}
/**
* Imagine a simple service / api client
*/
const someApiClient = {
/**
* @returns {Promise<string[]>} 3 first letters
*/
async getSomeData () {
return ['a', 'b', 'c']
}
}
/**
* Just a function or method using the api client, that has types declared
*/
async function fetchMeSomeDataHandler () {
return someApiClient.getSomeData()
}
const result = await request(() => fetchMeSomeDataHandler())
预计
在这里,我希望 vscode/jsdoc 推断“结果”的类型是字符串[],甚至给我来自 api 客户端的描述(“3 个首字母”)。
但它不是,它会在最后给出一个类型any
。
我们在 vscode 中得到了什么
如果我们跟踪 vscode 拾取的类型,我们可以看到它正在“一点一点地丢失类型”,直到什么都没有为止。
- 为 api 客户端获取的完整类型描述。
- 类型在处理程序定义中已知,但我们丢失了客户端值描述(3 个首字母)。
- 我们完全丢失了最终结果的类型信息
最佳答案
VS Code 会尝试根据函数参数的用法来推断函数参数的类型。一个简单的例子是:
function foo(a) {
return a.b;
}
foo({ b: 3 })
这导致 foo
具有签名 function foo(a: any): any
。您的代码是此限制的一个更复杂的示例。
修复方法是在request
上显式注释参数类型:
/**
* @template T
* @param {() => Promise<T>} handler
* @return {Promise<T>}
*/
async function request(handler) {
...
}
在这种特定情况下,我们还需要显式的 @returns
因为 catch block 不返回类型 T
的值(它返回一个 any
因为错误是未类型化的)。
如果编写了request
,您可以省略@returns
:
/**
* @template T
* @param {() => Promise<T>} handler
*/
async function request(handler) {
// common stuff
const result = await handler()
return result
}
因为 VS Code 可以推断函数的返回类型(但请记住,显式类型在许多情况下很有用,尤其是对于可能返回多种不同类型的函数)
添加显式类型后,result
应该具有正确的类型:
关于visual-studio-code - 如何使用 vscode 中的 jsdoc 在包装函数中正确获取返回值的推断类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63615171/