TypeScript 类型推断问题 [英] TypeScript type inference issue

查看:38
本文介绍了TypeScript 类型推断问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 TypeScript 与 MongoDB node.js 驱动程序一起使用.请注意,这不是 Mongo 问题,它只是我遇到的这个问题的特定用例.

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.

几乎每个 Mongo 调用都使用 (arg1, arg2, ..., argn, callback) 的模式,其中 callback 是一个接受 (错误,资源).但是,我想使用承诺.我试图通过编写一个辅助包装函数来简化我的用法,如下所示:

Pretty much every Mongo call uses a pattern of (arg1, arg2, ..., argn, callback) where callback is a function that accepts (err, res). However, I want to use promises. I'm trying to simplify my usage by writing a helper wrapper function, like so:

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;
}

这很好用,除了由于某种原因编译器无法推断 T 的类型.我必须拨打电话,例如:

This works great, except that for some reason the compiler cannot infer the type of T. I have to make calls such as:

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

如果我省略 部分,结果是 Promise<{}> 并且我失去了类型安全性.但是,编译器清楚地知道 Mongo 调用的 callback 参数是 (err: Error, db: Db) =>无效.

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

我该怎么做才能让编译器正确推断 T 的类型?

What can I do to get the compiler to correctly infer the type of T?

推荐答案

Typescript 能够推断一些泛型函数的类型,但它有一些限制.

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. 一个带有 1 个参数的简单函数.

function genericFunction<T>(value: T): T {
    return value;
}

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

这样就可以了,不需要手动指定 T 的类型.

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

  1. 一个带有 2 个泛型参数的函数.

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 的类型.

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

  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 的类型.

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

  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 的类型.

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

  1. 只接收从 T 到 T 的函数

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

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

这样就可以了,不需要手动指定 T 的类型.

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

  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 的类型.

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

  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")); 

这不再有效,需要手动指定类型.

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.

添加另一个 T 类型的参数可以修复它,但它与您的情况不太匹配.

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

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 的类型.

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

这篇关于TypeScript 类型推断问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆