Type inference not working as expected for generic function

RatTac

For a function I'd like to provide a data source in a generic way, e.g. either as url string or a callback that returns a Promise<string>

const processUrl = async (url: string | (() => Promise<string>)) => {
    //Retrieve url...
    const urlData = typeof url === "function" ? await url() : url;
    //Proceed...
};

This works, however I have problems generalizing this approach using a generic

type DataInput<T> = T | (() => Promise<T>);

const retrieveDataInput_Impl1 = <T, DataInputType extends DataInput<T>>(t: DataInputType): Promise<T> => typeof t === "function" ? t() : t;
//No error, but return type is always unknown

const retrieveDataInput_Impl2 = <T extends any>(t: DataInput<T>): Promise<T> => typeof t === "function" ? t() : t;
//Shows the following error for t(): This expression is not callable. Not all constituents of type '(() => Promise<T>) | (T & Function)' are callable. Type 'T & Function' has no call signatures.ts(2349)

const b1 = await retrieveDataInput_Impl1("a"); // type of b1 is unknown, getDataInput1 is showing no error
const b2 = await retrieveDataInput_Impl2("a"); // type of b2 is string, but getDataInput2 is showing an error

How could this functionality be implemented with full type safety?

DustInCompetent

Disallowing T to be a function fixes the ambiguity. You should also make the function async so it still returns a Promise when the argument is returned directly.

type DataInput<T> = T extends Function ? never : (() => Promise<T>) | T;
const retrieveDataInput_Impl3 = async <T>(t: DataInput<T>): Promise<T> => typeof t === "function" ? t() : t;

retrieveDataInput_Impl3('foo') // => Promise<"foo">
retrieveDataInput_Impl3({ key: 'value' }) // => Promise<{ key: string }>
retrieveDataInput_Impl3(async () => 123) // => Promise<number>
retrieveDataInput_Impl3(async () => {}) // => Promise<void>
retrieveDataInput_Impl3(() => {}) // => Error

This solution doesn't seem to accept T of type boolean though, because of some other issue.

Update

Since it doesn't matter whether an async function returns a value or a Promise of the value, you might as well allow passing any function and fix your error with a simple type assertion.

type DataInput<T> = (() => Promise<T>) | (() => T) | T;
const retrieveDataInput_Impl3 = async <T,>(t: DataInput<T>): Promise<T> =>
  typeof t === "function" ? (t as Function)() : t;

retrieveDataInput_Impl3(() => 42) // => Promise<number)>
retrieveDataInput_Impl3(async () => Promise.resolve(42)) // => Promise<number>
retrieveDataInput_Impl3(() => () => 42) // => Promise<() => number)>

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Type inference not working as expected for generic function

From Dev

Type inference of generic function parameter

From Dev

Generic type inference not working with method chaining?

From Dev

Is function pointer type in _Generic assoc-list not working as expected?

From Dev

Is function pointer type in _Generic assoc-list not working as expected?

From Dev

Type inference not working when passing map function

From Dev

Scala type inference not working with generic case class and lambda

From Dev

Generic type inference explanation

From Dev

Generic methods type inference

From Dev

FSharp: Type inference with generic

From Dev

Swift Generic Type Inference

From Dev

Type inference for functions passed to generic function wrappers like _.debounce

From Dev

Generic Type Inference with Class Argument

From Dev

Generics and type inference for a generic factory

From Dev

Generic type inference limits in Java

From Dev

strange issue with Generic type inference

From Dev

Generics and type inference for a generic factory

From Dev

Generic factory method and type inference

From Dev

Typescript: Generic class type inference

From Dev

type inference of (>>)(>>) (function composition)

From Dev

Type inference with function literals

From Dev

type inference of (>>)(>>) (function composition)

From Dev

Type inference in generic method & generic class

From Dev

Typescript: Constrain function generic type based on the expected return type

From Dev

Why Scala fail to recognize Null type as a subtype of T in generic function type parameter inference?

From Dev

Scala: type inference of generic and it's type argument

From Dev

Java type inference of generic exception type

From Dev

Local type inference and contravariance in generic type variables

From Dev

Scala generic type inference inconsistent with ClassTag

Related Related

  1. 1

    Type inference not working as expected for generic function

  2. 2

    Type inference of generic function parameter

  3. 3

    Generic type inference not working with method chaining?

  4. 4

    Is function pointer type in _Generic assoc-list not working as expected?

  5. 5

    Is function pointer type in _Generic assoc-list not working as expected?

  6. 6

    Type inference not working when passing map function

  7. 7

    Scala type inference not working with generic case class and lambda

  8. 8

    Generic type inference explanation

  9. 9

    Generic methods type inference

  10. 10

    FSharp: Type inference with generic

  11. 11

    Swift Generic Type Inference

  12. 12

    Type inference for functions passed to generic function wrappers like _.debounce

  13. 13

    Generic Type Inference with Class Argument

  14. 14

    Generics and type inference for a generic factory

  15. 15

    Generic type inference limits in Java

  16. 16

    strange issue with Generic type inference

  17. 17

    Generics and type inference for a generic factory

  18. 18

    Generic factory method and type inference

  19. 19

    Typescript: Generic class type inference

  20. 20

    type inference of (>>)(>>) (function composition)

  21. 21

    Type inference with function literals

  22. 22

    type inference of (>>)(>>) (function composition)

  23. 23

    Type inference in generic method & generic class

  24. 24

    Typescript: Constrain function generic type based on the expected return type

  25. 25

    Why Scala fail to recognize Null type as a subtype of T in generic function type parameter inference?

  26. 26

    Scala: type inference of generic and it's type argument

  27. 27

    Java type inference of generic exception type

  28. 28

    Local type inference and contravariance in generic type variables

  29. 29

    Scala generic type inference inconsistent with ClassTag

HotTag

Archive