简体   繁体   English

如何在 Typescript 中使用多态和泛型?

[英]How to use polymorphism with generics in Typescript?

If I have an object of type that take a generic T that extends another interface/type.如果我有一个类型的对象,它采用扩展另一个接口/类型的泛型 T。 How can I type an object/method param to allow any subtype generic.如何键入对象/方法参数以允许任何子类型泛型。

An exemple will be easier to understand:举个例子会更容易理解:

type Options = {
  id: string;
};

type Task<O extends Options = Options> = {
  start: (options: O) => void;
};

const t1: Task<Options> = {
  start: ({ id }) => {
    console.log(id);
  }
};
const t2: Task<{ id: "static"; foo: true } & Options> = {
  start: ({ id, foo }) => {
    console.log(id, foo);
  }
};

const TaskManager = {
  registerTask: (task: Task) => { // maybe I miss something here, I would like to avoid Task<any>
    // use task
  }
};
TaskManager.registerTask(t1); // Ok
TaskManager.registerTask(t2); // ERROR: Argument of type 'Task<{ id: "static"; foo: true; } & Options>' is not assignable to parameter of type 'Task<Options>'.

How can I modify registerTask to allow any Task that accept Task<T extends Options>如何修改registerTask允许任何Task接受Task<T extends Options>

Can someone help me to fix this typing issue ?有人可以帮我解决这个打字问题吗?

EDIT: Also, If TaskManager store an array of Task, how to type this array with generics ?编辑:另外,如果 TaskManager 存储一个 Task 数组,如何使用泛型键入这个数组?

class TaskManager {
  private static tasks: Task[] = [];
  public static registerTask = <O extends Options>(task: Task<O>) => {
    TaskManager.tasks.push(task); // ERROR: Argument of type 'Task<O>' is not assignable to parameter of type 'Task<Options>'
  };
}

I need to provide generic at class level ?我需要在类级别提供泛型?

Temporary solution is to declare an array of Task<any> :临时解决方案是声明一个Task<any>数组:

private static tasks: Task<any>[] = [];

to allow any subtypes.允许任何子类型。

You can make TaskManager.registerTask() a generic method like this:您可以使TaskManager.registerTask()成为这样的通用方法:

const TaskManager = {
  registerTask: <O extends Options>(task: Task<O>) => {

  }
};

which will then cause the compiler to infer O when you call it:这将导致编译器在您调用它时推断O

TaskManager.registerTask(t1); // okay
// (property) registerTask: <Options>(task: Task<Options>) => void

TaskManager.registerTask(t2); // okay
// (property) registerTask: <{ id: "static"; foo: true; } & Options>(
//   task: Task<{ id: "static";  foo: true; } & Options>
// ) => void

Playground link to code Playground 链接到代码

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

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