How to properly infer xxx
type to data
?
Restrictions:
- wrapper argument should accept only
Promise<{ xxx: Data; }>
- currently works. - only wrapper can be changed
function wrapper<
Data,
A extends Promise<{ xxx: Data; }>,
>(a: A): Promise<{ data: Data }> {
return 1 as any
}
async function a(): Promise<{ xxx: string }> {
return { xxx: 'a' }
}
wrapper(a()).then(res => {
const data: string = res.data // is unknown, how to make it infer string?
})
CodePudding user response:
Presumably you expect the compiler to infer A
as Promise<{ xxx: string }>
, and from there to infer Data
as string
because A extends Promise<{xxx: Data}>
. Unfortunately, in TypeScript, generic constraints like extends Promise<{xxx: Data}>
don't serve as inference sites for type parameters. (Such behavior was suggested in microsoft/TypeScript#7234 but was never implemented.) So the compiler has no idea what to infer Data
as, and thus it falls back to the unknown
type. Oops.
In order to get inference for Data
(which I will rename to D
to be more in keeping with the usual naming conventions for type parameters) from a
, you'll need to give a
a type which is directly related to D
. Here's the easiest way to do it:
function wrapper<D>(a: Promise<{xxx: D}>): Promise<{ data: D }> {
return 1 as any
}
You weren't really using A
in your code, so I left it out. Instead, we say that a
is of type Promise<{xxx: D}>
. The compiler can infer D
from that, by matching Promise<{xxx: string}>
to Promise<{xxx: D}>
.
Let's see it in action:
wrapper(a()).then(res => {
const data: string = res.data // okay
});
Looks good.