考虑以下人为的示例:
type Response = {
data: {
bar: number;
}
}
type MyData = {
bar: number;
}
const responses: Response[] = [/**/];
const data = responses
.map(response => response.data);
现在,如果您将鼠标悬停在IDE中的data
上,它会告诉您它的类型是{ bar: number }[]
,而将鼠标悬停在.map
函数上会给出一个更复杂(无法读取)的类型。在实际情况中,对于更复杂的类型,悬停信息变得完全无用,涉及这些类型的错误消息也是如此。
所以我想要的是一种方法来告诉TS我们想把它当作MyData
类型。我想达到以下效果:
const data = responses
.map(response => {
const data: MyData = response.data; // errors if response.data doesn't satisfy MyData
return data; // we're mapping to `MyData`, and not to `{bar : number}`
});
我不想使用不必要的中间变量。理想情况下,我会使用这样的东西:
const data = responses
.map(response => response.data with type MyData);
我有几个部分解决方案,但没有一个在现实世界的场景中工作得很好:
1:在Response
类型中使用MyData
type Response = { data : MyData }
这要求我们可以更改输入类型,但这并不总是一个选项。例如,我们的响应类型可能是自动生成的,或者来自库。
2:显式输入data
变量:
const data: MyData[] = responses.map(response => response.data);
虽然这使得data
的类型更有用,但它仍然保留了.map
的原始复杂类型。在不太人为的例子中,我们可能会链接几个操作(map
/filter
等),所有这些操作仍然使用无别名的类型签名。
3:使用as
强制转换
const data = responses.map(response => response.data as MyData);
这不安全如果response.data
更改为MyData | undefined
,那么上面的代码编译得很好,即使它被破坏了。
4:使用satisfies
强制转换
const data = responses.map(response => response.data satisfies MyData);
这是安全的,但不工作。它保留了原始类型(通过设计)。
5:显式设置类型参数
const data = responses.map<MyData>(response => response.data);
这对于我们的人造示例来说相当有效,但在现实世界的场景中,它并不总是有效。除了风格方面的考虑,主要问题是如果我们的操作需要多个类型参数,我们现在需要提供ALL参数。这是不可取的,有时甚至不可行。
因此,我正在寻找一种方法来“重新分配”值的类型,而不使用中间变量。有这种事吗?我如何才能做到这一点?
1条答案
按热度按时间nx7onnlm1#
您可以按如下方式注解arrow function的返回类型:
所以你可以这样调用
responses.map()
:其中
response
参数的类型仍然是上下文类型,因此您不必注解它。请注意,注解位于参数列表的右括号“
)
”和箭头“=>
”之间。如果你的函数只有一个参数,你仍然需要把它括在括号里才能编译。也就是说,你不能这样做:即使无注解的返回类型版本在没有括号的情况下也能正常工作:
遗憾的是,我找不到我认为的这个特性的“官方文档”。TypeScript Handbook描述了函数语句的返回类型注解,而(已存档且大部分已过时)language specification并没有像我希望的那样清楚地说明这一点,尽管它有一个关于箭头函数的部分。如果有人找到了这方面的权威文档(不包括编译器本身或一些使用但没有提到该功能的文档),我很乐意将其链接到这里。
Playground链接到代码