Home > Enterprise >  Infer typescript generic wrapper function return type property value
Infer typescript generic wrapper function return type property value

Time:05-02

How to properly infer xxx type to data?

Restrictions:

  • wrapper argument should accept only Promise<{ xxx: Data; }> - currently works.
  • only wrapper can be changed

Typescript sandbox

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.

Playground link to code

  • Related