如何在 vscode 中使用 jsdoc 正确获取包装函数中返回值的推断类型?
How to properly get inferred types of returned values in a wrapper function with jsdoc in vscode?
这里有一些代码(经过简化)可以更好地理解:
发送请求的包装器
- 它在请求发送和完成时做一些常见的事情。
- 它returns请求的结果(处理程序)。
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 块不 return 类型 T
的值(它 return 是 any
因为错误是无类型的)。
你可以省略 @returns
如果 request
写成:
/**
* @template T
* @param {() => Promise<T>} handler
*/
async function request(handler) {
// common stuff
const result = await handler()
return result
}
因为 VS Code 可以推断 return 类型的函数(但请记住,显式类型在许多情况下很有用,尤其是对于可能 return 多种不同类型的函数)
添加显式类型后,result
应该具有正确的类型:
这里有一些代码(经过简化)可以更好地理解:
发送请求的包装器
- 它在请求发送和完成时做一些常见的事情。
- 它returns请求的结果(处理程序)。
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 块不 return 类型 T
的值(它 return 是 any
因为错误是无类型的)。
你可以省略 @returns
如果 request
写成:
/**
* @template T
* @param {() => Promise<T>} handler
*/
async function request(handler) {
// common stuff
const result = await handler()
return result
}
因为 VS Code 可以推断 return 类型的函数(但请记住,显式类型在许多情况下很有用,尤其是对于可能 return 多种不同类型的函数)
添加显式类型后,result
应该具有正确的类型: