【问题标题】:Overwriting inherent type with own "more" correct - Typescript用自己的“更多”正确覆盖固有类型 - 打字稿
【发布时间】:2020-12-16 20:56:33
【问题描述】:

我有一个函数返回一个将使用反射解决的承诺。

(Promise with、resolve 和 reject 函数排队然后执行)

函数的输入是来自一个对象的方法,参数如 SingleTask 类型所示。

因为我没有在承诺打字稿中返回任何内容,所以将Promise<any> 作为结果。

但实际上,结果是 Promise<FIRST PARAM OF SINGLE TASK TYPE>> - Some function from an object

如何声明正确的返回类型

type AnyClass = { new (...arg0: any): any }

type SingleTask<V extends AnyClass> = {
  [P in keyof InstanceType<V>]-?: InstanceType<V>[P] extends (...a: any) => any
    ? [P, Parameters<InstanceType<V>[P]>]
    : never
}[keyof InstanceType<V>]

  addTaskToQueue(task: SingleTask<T>): Promise<ReturnType<**What i should put here ?** >> {
    return new Promise((resolve, reject) => {
      const instance = this.instances.pop()
      if (instance) {
        this.runTasksInQueue(instance, { task, resolve, reject })
      } else {
        this.queue.push({ task, resolve, reject })
      }
    })
  }

Typescript playground with full code

【问题讨论】:

  • 问题“我如何帮助 typescript 理解我将返回具有返回类型的函数的返回类型的承诺,该返回类型位于数组的第一个元素内,在输入中给出?”非常混乱。你能改写一下更清楚吗?也许用多个较短的句子而不是一个长的句子?此外,您的示例代码似乎不是minimal reproducible example;您能否编辑代码,以便任何人都可以将其放入像The TypeScript Playground 这样的独立 IDE 中并自己查看问题?祝你好运!
  • 我改写一下,我觉得现在更容易理解了。抱歉,英语不是我的母语

标签: typescript typescript-typings typescript-generics


【解决方案1】:

我假设你想要这种行为:

type SomeCtor = new () => { a(x: string, y: number): boolean, b(z: number): string }
declare const q: Queue<SomeCtor>;
const a = q.addTaskToQueue(["a", ["", 1]]); // Promise<boolean>;
const b = q.addTaskToQueue(["b", [1]]); // Promise<string>;

我也只会担心addTaskToQueue() 的类型签名,而不是您的实现以及实现如何与签名交互。从类型系统的角度来看,根据您定义的类型,我会做这样的事情:

declare class Queue<T extends AnyClass> {
  addTaskToQueue<S extends SingleTask<T>>(task: S): Promise<ReturnType<InstanceType<T>[S[0]]>>;
}

addTaskToQueue() 方法必须是泛型的,否则最好的办法是获取另一个联合作为返回类型,对应于整个 SingleTask&lt;T&gt; 联合。您希望返回类型取决于传入的SingleTask&lt;T&gt; 联合的哪个 成员。一旦我们有一个类型参数S 对应于SingleTask&lt;T&gt; 的某个成员,我们就可以表示返回输入为

Promise<ReturnType<InstanceType<T>[S[0]]>>

请注意,S[0] 将是传入的InstanceType&lt;T&gt; 的键,因此我们正在查找该属性。您可以验证这是否为您提供了我认为您想要的行为。

这就是问题的答案。


顺便说一句,尚不清楚为什么您的泛型T 是您总是使用InstanceType&lt;T&gt; 处理的构造函数类型。看起来你对T 类型的对象所做的唯一事情是调用new this.object(),它特别假设构造函数采用零参数。如果是这样,我建议将T 更改为实例类型本身,并将构造函数称为new()=&gt;T 类型:

type SingleTask<T> = {
  [P in keyof T]-?: T[P] extends (...a: any) => any
  ? [P, Parameters<T[P]>]
  : never
}[keyof T]

type Task<T> = {
  task: SingleTask<T>
  resolve: (value?: unknown) => void
  reject: (reason: any) => void
}

declare class Queue<T> {
  instances: T[];
  queue: Task<T>[];
  object: new () => T;
  addTaskToQueue<S extends SingleTask<T>>(task: S): Promise<ReturnType<T[S[0]]>>;
}

type SomeType = { a(x: string, y: number): boolean, b(z: number): string }
declare const q: Queue<SomeType>;
const a = q.addTaskToQueue(["a", ["", 1]]); // Promise<boolean>;
const b = q.addTaskToQueue(["b", [1]]); // Promise<string>;

这要简单得多。

Playground link to code

【讨论】:

  • 我收到一个错误 - “函数实现丢失或未立即在声明之后。”,我如何确保打字稿返回我声明返回的内容?因为事实上,我并没有解决其中的承诺
  • 抱歉,我需要minimal reproducible example,否则我将无法查看。您很可能无法轻松地让编译器验证您的实现是否与签名匹配。如果您确定它确实如此,那么您可以使用type assertions 告诉编译器不要担心它。我正在考虑超出问题范围的这些细节,因为您的问题是“我如何声明正确的返回类型”,这可能是关于类型签名而不是实现的问题。
猜你喜欢
  • 2020-10-27
  • 2021-06-09
  • 2018-04-10
  • 2020-06-13
  • 2020-05-26
  • 1970-01-01
  • 1970-01-01
  • 2019-01-18
  • 2018-09-30
相关资源
最近更新 更多