简体   繁体   English

如何:Typescript 嵌套打字 A <b<generic> > </b<generic>

[英]How TO: Typescript nested typing A<B<GENERIC>>

Is it possible to have this kind of typing in typescript?是否可以在 typescript 中进行这种键入?

interface Worker<T> {
    renderChunk: (projectUrl: string, from: number, to: number) => Promise<T>;
}

interface WorkerPool<W<U>> {
    addWorker(worker: W, address: number): void;

    getIdleWorker(): W | null;
}

But I also want some type of restriction that checks that W should be an implementation of Worker , let's say you have for example an implementation of Worker as follow:但我也想要某种类型的限制来检查W是否应该是Worker的一个实现,假设你有一个 Worker 的实现,如下所示:

class RenderWorker implements Worker<string[]> {
    renderChunk: (projectUrl: string, from: number, to: number) => Promise<string[]> {
         return Promise.resolve(['Foo'])
    }
}

The below implementation should be acceptable by typescript: typescript 应该可以接受以下实现:

class RenderWorkerPool implements WorkerPool<RenderWorker> {} 

however this one should not be acceptable as string is not an implementation of Worker然而,这个不应该被接受,因为string不是Worker的实现

class RenderWorkerPool implements WorkerPool<string> {} 

Yes, using constrained generic types , you can ensure that W extends Worker .是的,使用受约束的泛型类型,您可以确保W扩展Worker

interface WorkerPool<W extends AaWorker<any>> {
    addWorker(worker: W, address: number): void;

    getIdleWorker(): W | null;
}

Playground Link 游乐场链接

Because of the nested generic, if you want to reason about the type of the worker, you'll need to specify that as well:由于嵌套泛型,如果你想推断 worker 的类型,你还需要指定它:

interface WorkerPool<U, W extends AaWorker<U>> {
    addWorker(worker: W, address: number): void;

    getIdleWorker(): W | null;
}

Playground Link 游乐场链接

But, as Bernardo Duarte points out in the comments, you might not need generics for Worker at all.但是,正如Bernardo Duarte在评论中指出的那样,您可能根本不需要 generics 作为 Worker。 Instead, just take any conforming Worker implementation with the right generic type:相反,只需采用具有正确泛型类型的任何符合标准的 Worker 实现:

interface WorkerPool<U> {
    addWorker(worker: AaWorker<U>, address: number): void;

    getIdleWorker(): AaWorker<U> | null;
}

Playground Link 游乐场链接

(I've changed Worker to AaWorker above, just so there's no naming conflict between your Worker and the Web Worker built-in objects.) (我已将上面的Worker更改为AaWorker ,这样您的 Worker 和 Web Worker 内置对象之间就不会发生命名冲突。)

I think you want this:我想你想要这个:

interface WorkerPool<W extends Worker<unknown>> {
  addWorker(worker: W, address: number): void;
  getIdleWorker(): W | null;
}

W is constrained by Worker<unknown> . WWorker<unknown>约束。 So W is inferred to be a Worker , and the generic T of that worker is also inferred as part of that.因此W被推断为Worker ,并且该工人的通用T也被推断为其中的一部分。

class RenderWorkerPoolA implements WorkerPool<RenderWorker> {} // fine
class RenderWorkerPoolB implements WorkerPool<string> {} // Type 'string' does not satisfy the constraint 'Worker<unknown>'

Playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM