Dav*_*fer 5 type-inference type-safety typescript
我在MongoDB node.js驱动程序中使用TypeScript。请注意,这不是一个Mongo问题,它只是我遇到的这个问题的特殊用例。
几乎每个Mongo调用都使用一个(arg1, arg2, ..., argn, callback)其中callback接受函数的模式(err, res)。但是,我想使用承诺。我试图通过编写一个辅助包装函数来简化用法,如下所示:
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;
}
Run Code Online (Sandbox Code Playgroud)
这很好用,除了出于某种原因编译器无法推断的类型T。我必须打如下电话:
var dbPromise = mongoWrap<mongodb.Db>(cb => mongoClient.connect("mongodb://localhost:27017/database", cb));
Run Code Online (Sandbox Code Playgroud)
如果我省略该<mongodb.Db>零件,结果将是Promise<{}>并且我失去类型安全性。但是,编译器显然知道callbackMongo调用的参数是(err: Error, db: Db) => void。
我该怎么做才能使编译器正确推断出类型T?
Typescript 能够推断一些泛型函数的类型,但它有一些限制。
由于手册的通用部分中没有任何信息,我决定进行一些测试并查看它在哪里出现问题。
function genericFunction<T>(value: T): T {
return value;
}
// type of val is Window
let val = genericFunction(window);
Run Code Online (Sandbox Code Playgroud)
这是可行的,不需要手动指定 T 的类型。
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);
Run Code Online (Sandbox Code Playgroud)
这是可行的,不需要手动指定 T 的类型。
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 ");
Run Code Online (Sandbox Code Playgroud)
这是可行的,不需要手动指定 T 的类型。
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 ");
Run Code Online (Sandbox Code Playgroud)
这是可行的,不需要手动指定 T 的类型。
function onlyCallback<T>(action: () => T) : T {
return action();
}
// type of val is string
let val = onlyCallback(()=> "abc");
Run Code Online (Sandbox Code Playgroud)
这是可行的,不需要手动指定 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");
Run Code Online (Sandbox Code Playgroud)
这是可行的,不需要手动指定 T 的类型。
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"));
Run Code Online (Sandbox Code Playgroud)
这不再有效,需要手动指定类型。
由于编译器目前受到限制,我想您必须为这种情况指定类型。这也是手册中针对类型推断失败的情况给出的解决方案。
添加另一个 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");
Run Code Online (Sandbox Code Playgroud)
这是可行的,不需要手动指定 T 的类型。
| 归档时间: |
|
| 查看次数: |
979 次 |
| 最近记录: |