在下面的代码中,我尝试创建一个类型安全的函数来访问给定输入的data
属性。我的目标是避免在任何地方重复访问data
,并且为此值得,我希望将样板保持在最低限度(例如,我希望TypeScript推断出尽可能多的类型)。
interface User {
name: string
}
interface HttpResponse<T> {
data: T
status: number
}
type HttpPromise<T> = Promise<HttpResponse<T>>
function fetch<T>(url: string): HttpPromise<T> {
return
}
function getData<T>(response: HttpResponse<T>): T {
return response.data
}
// Doesn't work: 'Promise<{}>' is not assignable to type 'Promise<User>'.
function fetchUser(): Promise<User> {
return fetch('https://...').then(getData)
}
我知道如何通过明确说明更多类型来使其工作,但我不知道为什么这不起作用。特别是:
{}
类型来自哪里(Promise<{}>
)?答案 0 :(得分:2)
让我们从解决方案开始:
function fetchUser(): Promise<User> {
return fetch<User>('https://...').then(getData)
}
为了使类型推断起作用,我们需要为TypeScript提供一个起点,在这种情况下,它是我们用来启动执行的函数。如果我们让获取方法通用T参数具有默认值(即{}),那么TypeScript将使用该类型来确定所有连接的函数调用,基本上是然后和 getData 继承该默认类型。最后,当TypeScript到达必须验证最后一个函数签名( getData )和外部 fetchUser 签名之间的类型正确性时,它会发现冲突,因为与{}类型和 fetchUser 一起明确表明它适用于用户类型。
当你完全省略fetchUser函数返回的类型时,你可以比较TypeScript将如何计算返回类型:
function fetchUser() {
return fetch<User>('https://...').then(getData)
}
如果将鼠标悬停在 fetchUser 函数上,您将看到TypeScript从内部 fetch 函数签名中推断出User类型,并且仍然是Promise&lt;使用者&gt;
答案 1 :(得分:1)
对于您的第一个问题,TypeScript抱怨类型为Promise<{}>
的原因是,如果您没有为返回promise的泛型函数指定类型,则默认为{{1} }。
考虑到这一点,通过调用Promise<{}>
而不提供类型参数,TypeScript将推断它是fetch('http://...')
。
我认为您可以在Promise<HttpResponse<{}>>
中调用User
时指定fetch
类型,从而使其成功:
fetchUser
如果你直接回复return fetch<User>('https://...').then(getData);
,那么你正在寻找的推论就会奏效。类似的东西:
fetch
但是,由于您正在联系该调用,因此async function getValueAsync<T>(): Promise<T> {
return null;
}
function testGetValueAsync(): Promise<User> {
return getValueAsync();
}
调用中没有任何内容告诉TypeScript它返回的是什么类型。
因此,您需要进行的最小更改是在调用fetch
时指定User
类型
fetch