我试图设计一种方法来声明可以返回Promise或rxjs Observable或具有特定返回类型的大多数Stream的函数,但是我不知道在打字稿中声明此函数的正确方法。
通常,我希望在代码中输入以下内容:
class Action<T> {
dispatcher: Function
constructor(dist) {
this.dispatcher = dist
}
f = <T>(s: string): T<string> => this.dispatcher('hello'+s)
}
通过这种方式,我得到错误:'T不是通用的'
对我来说T可以是一个Promise或一个Observable或一个Stream
如果我有类似的东西,我可以声明一个特定的调度程序,该调度程序根据声明的方式返回所需的值
const promiseDispacher = (x:any)=>Promise.resolve(x)
const observableDispacher = (x:any)=>Observable.of(x)
我想拥有的功能是当我调用函数f时能够以不同的方式使用
const a = new Action<Promise>(promiseDistpacher)
a.f('random string').then((s: string)=>{
....
})
或
const a = new Action<Observable>(observableDistpacher)
a.f('random string').subscribe((s: string)=>{
....
})
已更新
f
是一个执行一些操作并使用分派器将结果包装在特定的T
(Promise或Stream)中并返回到执行该功能的类的函数
答案 0 :(得分:2)
尽管我不确定自己在做什么,但我将尝试回答这个问题。首先,让T
成为传入的调度程序返回的通用类型,例如Promise<any>
或Observable<any>
或ReadableStream<any>
:
class Action<T> {
dispatcher: (x: any) => T;
constructor(dist: (x: any) => T) {
this.dispatcher = dist
}
f = (s: string) => this.dispatcher('hello' + s);
}
const promiseDispatcher = (x: any) => Promise.resolve(x)
const a = new Action(promiseDispatcher);
a.f("random string").then((s: string) => {
// ...
}); // works
这现在有效,并且f
的{{1}}类型被推断为Action<T>
类型,并且由于(s: string) => T
是a
,那么Action<Promise<any>>
是a.f(s)
。请注意,尽管Promise<any>
的返回类型为f
,但是T
本身并不是通用函数。通用参数位于 class 上,一旦有了该类的具体实例,它的f
函数也是一个具体的函数类型。
这里的一个问题是,您可能并不真的希望f
成为a.f(s)
,而是希望看到Promise<any>
。事实证明,由于TypeScript当前不非常支持higher kinded types,因此没有 general 的说法可以使Promise<string>
像T
或{{1 }}或Promise
,它们本身是通用类型。使用conditional types,您可以选择一些硬编码类型,例如Observable
,ReadableStream
和Promise<any>
,并将它们转换为Observable<any>
,ReadableStream<any>
和{ {1}}:
Promise<string>
现在,如果我们constrain Observable<string>
使用那些硬编码类型并使用上面的类型函数,我们应该会得到类似您想要的ReadableStream<string>
的类型:
type AppliedToString<T> =
T extends Promise<any> ? Promise<string> :
T extends Observable<any> ? Observable<string> :
T extends ReadableStream<any> ? ReadableStream<string> :
T;
现在,如果您检查T
的返回类型,您将看到它是f
。
这样做的不利之处是您需要维护一个硬编码列表,而且它也不是特别安全的类型,因为它可以让您传递返回// constrain T
class Action<T extends Promise<any> | Observable<any> | ReadableStream<any>> {
dispatcher: (x: any) => T;
constructor(dist: (x: any) => T) {
this.dispatcher = dist
}
// assert return type of f as AppliedToString<T>
f = (s: string) => this.dispatcher('hello' + s) as AppliedToString<T>;
}
const promiseDispatcher = (x: any) => Promise.resolve(x);
const a = new Action(promiseDispatcher);
a.f("random string").then((s: string) => {
// ...
}); // works
并将其视为{ {1}} ...将在运行时爆炸。
如果我试图变得更简单,更类型安全,则将a.f
限制为Promise<string>
,Promise<number>
或Promise<string>
,并忘记了映射,但是需要使用传入的调度程序获取T
并返回Promise<string>
:
Observable<string>
好的,希望其中一个或多个对您有所帮助。祝你好运!