TypeScript type inference problem

I am using TypeScript with the MongoDB node.js. driver Notice this is not a Mongo issue, its just a concrete use case for this problem that I have.

Almost every Mongo call uses a template (arg1, arg2, ..., argn, callback), where callbackis the function that takes (err, res). However, I want to use promises. I am trying to simplify my use by writing a helper shell, for example:

function mongoWrap<T>(action: (callback: (err: Error, res: T) => void) => void) : q.IPromise<T>
{
    var promise = q.Promise<T>((resolve, reject) => {
       action((err, res) => {
           if (err) reject(err);
           else resolve(res);
       });
    });

    return promise;
}

This works fine, except for some reason the compiler cannot infer the type T. I have to make calls like:

var dbPromise = mongoWrap<mongodb.Db>(cb => mongoClient.connect("mongodb://localhost:27017/database", cb));

If I omit the part <mongodb.Db>, the result is equal Promise<{}>, and I lose type safety. However, the compiler clearly knows that the argument callbackto invoke Mongo is (err: Error, db: Db) => void.

, T?

+4
2

Typescript , .

, , .

  • , 1 .
function genericFunction<T>(value: T): T {
    return value;
}

// type of val is Window
let val = genericFunction(window); 

, T .

  1. generic.
function genericFunction2<T>(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); 

, T .

  1. , .
function callBackAndValue<T>(action: (value: T) => T, value: T): T {
    return action(value);
}

// type of val is string
let val = callBackAndValue((value: string) => value + "5", "abc "); 

, T .

  1. , , .
function callBackAndValueWithPromise<T>(action: (value: T) => T, value: T): Promise<T> {
    return new Promise<T>((resolve, reject) => {
        resolve(action(value));
    });
}

// type of val is Promise<string>
let val = callBackAndValueWithPromise((value: string) => value + "5", "abc "); 

, T .

  1. , T T
function onlyCallback<T>(action: () => T) : T {
    return action();
}

// type of val is string
let val = onlyCallback(()=> "abc"); 

, T .

  1. , T, .
function onlyCallbackWithPromise<T>(action: () => T): Promise<T> {
    return new Promise<T>((resolve, reject) => { 
        resolve(action());
    });
}

// the type of val is Promise<string>
let val = onlyCallbackWithPromise(()=> "abc"); 

, T .

  1. , , . .
function typeFromCallbackOfCallback<T>(action: (callback: (value: T) => void) => void): Promise<T> {
    return new Promise<T>((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")); 

, .

, , , . , , , .

T , .

function lastOne<T>(action: (callback: (value: T) => void) => void, b: T): Promise<T> {
    return new Promise<T>((resolve, reject) => {
        action((value) => {
            resolve(value);
        });
    });
}

// type of var is Promise<string>
let var = lastOne(cb => cb("abc"), "a");

, T .

+3

, #. TypeScript, #, :

using System.IO;
using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        Console.WriteLine("Hello, World!");
        var task = Wrapper(cb => FakeMongoFunctionWithCallback(5, cb));
    }

    static void FakeMongoFunctionWithCallback(int arg, Action<Exception, int> callback)
    {
        // just pass through the arg into the callback, pretending we went to a db and came back with that result
        callback(null, arg);
    }

    static Task<T> Wrapper<T>(Action<Action<Exception, T>> action) {
        var tcs = new TaskCompletionSource<T>();
        action((err, res) => {
            if (err != null) tcs.SetException(err);
            else tcs.SetResult(res);
        });

        return tcs.Task;
    } 
}
+1

Source: https://habr.com/ru/post/1622221/


All Articles