Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
511 views
in Technique[技术] by (71.8m points)

typescript - Infer class argument type from super call

In my project using discord.js, there is a ClientEvents interface that holds event argument tuple types:

interface ClientEvents {
  ready: [];
  warn: [reason: string]
  message: [message: Message];
  // ...some more events
}

I also have an EventHandler class, which takes a type argument:

abstract class EventHandler<E extends keyof ClientEvents> {

  protected constructor(public eventName: E) {}

  abstract execute(...args: ClientEvents[E]): void;
}

The problem is that I can't extend this class using type inference for E, even if it's explicitly set in the super() call:

// Error: Generic type 'EventHandler<E>' requires 1 type argument(s).
class ReadyHandler extends EventHandler {

  public constructor() {
    super('ready'); // I want to infer the type using this argument
  }

  public execute() {
    // Some more code
  }
}

Is there a way to infer class argument types using the arguments of a super() call?

question from:https://stackoverflow.com/questions/65836052/infer-class-argument-type-from-super-call

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

No, not easily; inference generally doesn't work that way. You could, of course, write it out:

class ReadyHandler extends EventHandler<"ready"> {    
  public constructor() {  super('ready');  }    
  public execute() {}
}

If you want to avoid that redundancy you could refactor or encapsulate EventHandler so that you give it an actual string of type E and E will be inferred from it. The resulting class will no longer be generic. For example:

function SpecificHandler<E extends keyof ClientEvents>(eventName: E) {
  abstract class SpecificHandler extends EventHandler<E> {
    constructor() { super(eventName) };
  }
  return SpecificHandler;
}

class MessageHandler extends SpecificHandler("message") {
  public execute(msg: Message) {

  }
}

I'm not sure it's worth it, though.

Playground link to code


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...