子类作为参数的打字稿定义

Vin*_*t P 5 javascript typescript

我正在尝试为Flummox编写类型定义,但我不完全理解应该如何编写它。要点是我们应该对 Store、Actions 和 Flummox 类进行子类化,并将它们传递给函数。
以下是包含操作的代码示例:

import { Flummox, Actions, Store } from 'flummox';
class MessageActions extends Actions {
  newMessage(content: string) {
    return content;
  }
 }
class MessageStore extends Store {
   constructor(flux: Flummox) {
   super();

   const messageActions: MessageActions = flux.getActions('messages'); // error here
   this.register(messageActions.newMessage, this.handleNewMessage);
  }
 }

 class Flux extends Flummox {
   constructor() {
     super();

     this.createActions('messages', MessageActions);
     this.createStore('messages', MessageStore, this); //error here
   }
 }
Run Code Online (Sandbox Code Playgroud)

我开始的定义是:

/// <reference path="eventemitter3.d.ts"/>

declare module "flummox" {

  type ActionId = string;

  class Store {
    register(action: ActionId | Function, handler: Function): void;
  }

  class Actions {

  }

  class Flummox extends EventEmitter3.EventEmitter.EventEmitter3 {
    createActions(key: string, actions: Actions, constructorArgs?: any | any[]): Actions;
    getActions(key: string): Actions;
    removeActions(key: string): Actions;

    createStore(key: string, store: Store, constructorArgs?: any | any[]): Store;
    getStore(key: string): Store;
    removeStore(key: string): Store;
 }
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

src/app/App.ts(16,11): error TS2322: Type 'Actions' is not assignable to type 'MessageActions'. Property 'newMessage' is missing in type 'Actions'. src/app/App.ts(35,34): error TS2345: Argument of type 'typeof MessageStore' is not assignable to parameter of type 'Store'. Property 'register' is missing in type 'typeof MessageStore'.'.

这很公平,因为我知道我可能应该使用接口,但那样我将无法扩展代码中的类。如果您想尝试一下,这里有一个存储库的链接

有人能帮助我吗?我觉得我错过了一些明显的东西

Arn*_*ion 5

正如 IRC 上所讨论的,createStore(store: Store) 意味着 createStore 采用Store 类型(或其子类型)的实例,而不是Store 子类型的类型。对于后者,您希望 store 的类型包含返回 Store 或 Store 子类型的构造签名。所以

createActions(key: string, actions: Actions, constructorArgs?: any | any[]): Actions;
Run Code Online (Sandbox Code Playgroud)

应该是

createActions(key: string, actions: { new(...args: any[]): Actions }, constructorArgs?: any | any[]): Actions;
Run Code Online (Sandbox Code Playgroud)

或者

createActions<T extends Actions>(key: string, actions: { new(...args: any[]): T }, constructorArgs?: any | any[]): T;
Run Code Online (Sandbox Code Playgroud)

后者允许您返回传入的相同类型,而不是总是返回操作(如果您需要的话)。

createStore() 也需要做同样的事情


this.register(messageActions.newMessage, this.handleNewMessage);
Run Code Online (Sandbox Code Playgroud)

会导致问题,因为this在handleNewMessage中未定义。this.handleNewMessage 返回一个函数,而不是像其他语言中那样的绑定委托。您要么想要this.handleNewMessage.bind(this),要么message => this.handleNewMessage(message)- 后一种形式要求您显式写出所有参数,而前一种形式则不需要,但如果要注册的参数的签名和 handleNewMessage 的签名不一致,则会丢失类型检查错误。