TypeScript type inference issue

后端 未结 2 551
一生所求
一生所求 2021-01-13 08:10

I\'m using TypeScript with the MongoDB node.js driver. Note, this is not a Mongo question, its just the particular use case of this issue I\'m having.

Pretty much ev

2条回答
  •  情深已故
    2021-01-13 08:32

    Typescript is able to infer the type of some generic functions but it has some limitations.

    Since there isn't any information in the generic section of the handbook I decided to make some tests and see where it breaks down.

    1. a simple function that takes 1 parameter.
    function genericFunction(value: T): T {
        return value;
    }
    
    // type of val is Window
    let val = genericFunction(window); 
    

    This works, there's no need to specify the type of T manually.

    1. a function with 2 generic parameters.
    function genericFunction2(value: T, anotherValue: T) : T {
        return value;
    }
    
    // type of val is String
    let val = genericFunction2("b", "5"); 
    
    // compilation error type of T can't be inferred from usage
    let anotherVal = genericFunction2("b", 5); 
    

    This works, there's no need to specify the type of T manually.

    1. a function that receives a callback and a value.
    function callBackAndValue(action: (value: T) => T, value: T): T {
        return action(value);
    }
    
    // type of val is string
    let val = callBackAndValue((value: string) => value + "5", "abc "); 
    

    This works, there's no need to specify the type of T manually.

    1. a function that receives a callback and a value but returns a promise.
    function callBackAndValueWithPromise(action: (value: T) => T, value: T): Promise {
        return new Promise((resolve, reject) => {
            resolve(action(value));
        });
    }
    
    // type of val is Promise
    let val = callBackAndValueWithPromise((value: string) => value + "5", "abc "); 
    

    This works, there's no need to specify the type of T manually.

    1. a function that receives only a function from T to T
    function onlyCallback(action: () => T) : T {
        return action();
    }
    
    // type of val is string
    let val = onlyCallback(()=> "abc"); 
    

    This works, there's no need to specify the type of T manually.

    1. A function that receives a function from nothing to T that returns a promise.
    function onlyCallbackWithPromise(action: () => T): Promise {
        return new Promise((resolve, reject) => { 
            resolve(action());
        });
    }
    
    // the type of val is Promise
    let val = onlyCallbackWithPromise(()=> "abc"); 
    

    This works, there's no need to specify the type of T manually.

    1. A function that receives the a function that takes a function. The case in the question.
    function typeFromCallbackOfCallback(action: (callback: (value: T) => void) => void): Promise {
        return new Promise((resolve, reject) => {
            action((value) => {
                resolve(value);
            });
        });
    }
    
    // here the compiler fails to infer the type cb should take as a parameter and it seems to default to object({})
    // type of Val is Promise<{}>
    let val = typeFromCallbackOfCallback(cb => cb("abc")); 
    

    This no longer works and needs the type to be specified manually.

    Since the compiler is limited at the moment I guess you are stuck having to specify the type for this case. That is the solution given in the handbook as well for the cases when type inference fails.

    Adding another parameter of type T fixes it, but It doesn't quite match your case.

    function lastOne(action: (callback: (value: T) => void) => void, b: T): Promise {
        return new Promise((resolve, reject) => {
            action((value) => {
                resolve(value);
            });
        });
    }
    
    // type of var is Promise
    let var = lastOne(cb => cb("abc"), "a");
    

    This works, there's no need to specify the type of T manually.

提交回复
热议问题