首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何声明泛型类泛型?

如何声明泛型类泛型?
EN

Stack Overflow用户
提问于 2019-01-10 16:25:12
回答 1查看 150关注 0票数 3

我试图设计一种方法来声明一个函数,该函数可以返回具有特定返回类型的允诺或rxjs、可观察的或最多的Stream,但我不知道如何在类型记录中声明此函数。

一般来说,我希望代码中有这样的内容:

代码语言:javascript
复制
class Action<T> {
    dispatcher: Function
    constructor(dist) {
        this.dispatcher = dist
    }

    f = <T>(s: string): T<string> => this.dispatcher('hello'+s)
}

这样我就得到了错误:“t不是泛型的”

对我来说,T可以是一个承诺,一个可以观察到的,或者是一条溪流

如果我能够有类似的东西,我可以声明一个特定的分配器,根据我声明它的方式来返回我想要的值

代码语言:javascript
复制
const promiseDispacher = (x:any)=>Promise.resolve(x)
const observableDispacher = (x:any)=>Observable.of(x)

我想拥有的是当我调用函数f时能够以不同的方式使用的能力。

代码语言:javascript
复制
 const a = new Action<Promise>(promiseDistpacher)
 a.f('random string').then((s: string)=>{
   ....
 })

代码语言:javascript
复制
 const a = new Action<Observable>(observableDistpacher)
 a.f('random string').subscribe((s: string)=>{
   ....
 })

更新

f是一个函数,它执行一些操作,并使用dispatcher将结果包装在特定的T (承诺或流)中,然后返回给执行该函数的类

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-10 19:10:01

我要试着回答这个问题,尽管我并不确定你在做什么。首先,让我们将T设置为传入分派程序返回的泛型类型,类似于Promise<any>Observable<any>ReadableStream

代码语言:javascript
复制
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

这现在起作用了,fAction<T>类型被推断为(s: string) => T类型,因为aAction<Promise<any>>,所以a.f(s)Promise<any>。注意,尽管f有一个返回类型的T,但f本身并不是泛型函数。泛型参数在类上,一旦有了类的具体实例,它的f函数也是一个具体的函数类型。

这里的一个问题是,您可能并不希望a.f(s)成为一个Promise<any>,而是希望看到一个Promise<string>。事实证明,由于TypeScript目前不太支持高类,所以没有通用的方法来使T类似于PromiseObservableReadableStream,它们本身就是泛型类型。使用条件类型,您可以选择一些硬编码类型,如Promise<any>Observable<any>ReadableStream<any>,并分别将它们转换为Promise<string>Observable<string>ReadableStream<string>

代码语言:javascript
复制
type AppliedToString<T> =
  T extends Promise<any> ? Promise<string> :
  T extends Observable<any> ? Observable<string> :
  T extends ReadableStream<any> ? ReadableStream<string> :
  T;

现在,如果我们将约束 T转换为这些硬编码类型,并使用上面的type函数,我们应该得到类似于f所需的类型。

代码语言:javascript
复制
// 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

现在,如果您检查a.f的返回类型,您将看到它是一个Promise<string>

这样做的缺点是您需要维护一个硬编码列表,而且它也不是特别的类型,因为它将允许您传入一个返回Promise<number>的调度程序,并把它当作一个Promise<string>.会在运行时爆炸。

如果我试图变得更简单,更多类型,我会将T限制为Promise<string>Observable<string>ReadableStream<string>,而忘记映射,但要求传入的调度程序获取一个string并返回一个T

代码语言:javascript
复制
class Action<T extends Promise<string> | Observable<string> | ReadableStream<string>> {
  dispatcher: (x: string) => T;
  constructor(dist: (x: string) => T) {
    this.dispatcher = dist
  }
  f = (s: string) => this.dispatcher('hello' + s);
}
// note that x is type string in this:
const promiseDispatcher = (x: string) => Promise.resolve(x)
const a = new Action(promiseDispatcher);
a.f("random string").then((s: string) => {
  // ...
})

好吧,希望其中一个或多个能帮到你。祝好运!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54132960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档