2017-10-14 72 views
0

我试图在TypeScript中创建async库的*-as-promised version,重用@types/async类型。如何在TypeScript中合并单独的函数声明?

我的问题是@types/async at the .filter function是出口两个函数类型具有相同的名称:

export function filter<T, E>(arr: T[] | IterableIterator<T>, iterator: AsyncBooleanIterator<T, E>, callback?: AsyncResultArrayCallback<T, E>): void; 
export function filter<T, E>(arr: Dictionary<T>, iterator: AsyncBooleanIterator<T, E>, callback?: AsyncResultArrayCallback<T, E>): void; 

但我only export one .filter function

function filter<T>(
    arr: async.Dictionary<T> | T[] | IterableIterator<T>, 
    iterator: (item: T) => Promise<boolean> 
): Promise<Array<(T | undefined)> | undefined> { 
    return new Promise((resolve, reject) => { 
    async.filter(arr, (item, cb) => { 
     iterator(item) 
     .then(res => cb(undefined, res)) 
     .catch(err => cb(err)); 
    }, (err, results) => 
     err 
     ? reject(err) 
     : resolve(results) 
    ); 
    }); 
} 

编译时,这给了我以下错误:

lib/filter.ts(32,18): error TS2345: Argument of type 'Dictionary<T> | IterableIterator<T> | T[]' is not assignable to parameter of type 'Dictionary<T>'. 
    Type 'IterableIterator<T>' is not assignable to type 'Dictionary<T>'. 

那么,我怎样才能合并这些声明在一个?

谢谢你。

回答

1

奇怪的是,键入不是一个单一的函数签名,并且参数为arr的三种可能类型的联合。您可能需要考虑向async输入库提交问题或拉取请求以解决问题。

即便如此,如果编译器允许您按照自己的方式调用该函数,那将会很不错,因为您知道这样做是安全的。但正如你所看到的,至少在TypeScript v2.5中是这样的,it won't

最简单的解决办法:既然你知道一个事实,什么编译器不知道......即,现有的filter功能确实会接受T[] | IterableIterator<T> | Dictionary<T>类型的arr,它是安全的告诉编译器不要担心通过断言arrany类型的即禁用类型检查:

function filter<T>(
    arr: async.Dictionary<T> | T[] | IterableIterator<T>, 
    iterator: (item: T) => Promise<boolean> 
): Promise<Array<(T | undefined)> | undefined> { 
    return new Promise((resolve, reject) => { 
    async.filter(arr as any, (item, cb) => { 
     iterator(item) 
     .then(res => cb(undefined, res)) 
     .catch(err => cb(err)); 
    }, (err, results) => 
     err 
     ? reject(err) 
     : resolve(results) 
    ); 
    }); 
} 

还有其他的解决方法,如写user-defined type guard到呼叫到async.filter()分成取决于arr类型两个呼叫;或者用类似于intersectFunction()的东西包装async.filter函数,以便它接受你想要的联合,但是这些解决方法体积较大并且具有运行时效果,所以我坚持上面的as any方法。

希望有帮助;祝你好运!

+0

我会用这个解决方案,谢谢@jcalz! –