javascript - Exportovanie variantu triedy


Snažím sa exportovať nejakú variáciu triedy, ktorú chcem importovať niekde inde. Neviem, či je možné ich vytvoriť bez inštancie? A ako to môžem urobiť.

Toto je to, čo mám teraz

index.ts

export { Character } from './Character';

Character.ts

import { CharacterOptions, WarlockOptions } from './CharacterOptions';

class Character implements CharacterInterface {
  private health: number;
  private name: string;
  private characterOptions: CharacterOptions;

  constructor(name, health) {
    this.name = name;
    this.health = health;
    this.characterOptions = new WarlockOptions(); // where WarlockOptions extends CharacterOptions
  }
}

Chcel by som byť schopný robiť niečo také v súbore index.ts

import { Character } from './Character';
import { ArcherOptions, WarlockOptions } from './CharacterOptions';

export const ArcherClass = someWrapperOfCharacter(ArcherOptions);
export const WarlockClass = someWrapperOfCharacter(WarlockOptions);

ako dynamicky vytvárať (cez someWrapperOfCharacter()) novú konkrétnu triedu, ktorú môžem sprístupniť.

Vieme, že môžem priamo vytvoriť triedy, ktoré rozširujú Character, ale snažím sa tomu vyhnúť, pretože:

  • Neviem, koľko CharacterOptions budem mať v budúcnosti
  • Chcel by som, aby som nebol nútený vytvárať novú variáciu zakaždým, keď chcem pridať novú CharacterOptions
  • Chcem umožniť priamo vytvoriť vlastnú triedu odovzdaním vlastného objektu, ktorý rozširuje CharacterOptions

Odpoveď č. 1

Do konštruktora triedy môžete odovzdať možnosti a mať funkciu, ktorá vytvára odvodené typy, ktoré nastavia triedu možností na konkrétnu implementáciu:

interface CharacterInterface { }

class CharacterOptions { public level?: number }
class ArcherOptions extends CharacterOptions { public bow?: string; }
class WarlockOptions extends CharacterOptions { public magic?: string }


class Character<T extends CharacterOptions> implements CharacterInterface {
    private health: number;
    private name: string;
    private characterOptions: T;

    constructor(name: string, health: number, optionsCtor: new () => T) {
        this.name = name;
        this.health = health;
        this.characterOptions = new optionsCtor(); // where WarlockOptions extends CharacterOptions
    }
}
function someWrapperOfCharacter<T extends CharacterOptions>(optionsCtor: new () => T) {
    return class extends Character<T> {
        constructor(name: string, health: number) {
            super(name, health, optionsCtor);
        }
    }
}

export const ArcherClass = someWrapperOfCharacter(ArcherOptions);
export type ArcherClass = InstanceType<typeof ArcherClass> // needed to allow type declarations let a: ArcherClass

export const WarlockClass = someWrapperOfCharacter(WarlockOptions);
export type WarlockClass = InstanceType<typeof WarlockClass>

Odpoveď č. 2

Skúšal som odpoveď Titiana, ale úplne ma to nespoľahlivo neuspokojilo (hoci mi to veľmi pomohlo).

Nakoniec som napísal obal takto:

interface CharacterInterface { }

class CharacterOptions { public level?: number }
class ArcherOptions extends CharacterOptions { public bow?: string; }
class WarlockOptions extends CharacterOptions { public magic?: string }

export const someWrapperOfCharacter = (optionsCtor: CharacterOptions) => {
  return class Character implements CharacterInterface {
    private health: number;
    private name: string;
    private characterOptions: CharacterOptions;

    constructor(name: string, health: number) {
      this.name = name;
      this.health = health;
      this.characterOptions = new optionsCtor(); 
    }
  }
};

export const ArcherClass = someWrapperOfCharacter(ArcherOptions);
export type ArcherClass = InstanceType<typeof ArcherClass> // needed to allow type declarations let a: ArcherClass

export const WarlockClass = someWrapperOfCharacter(WarlockOptions);
export type WarlockClass = InstanceType<typeof WarlockClass>

const archer = new ArcherClass('archie', 100);
console.log(archer instanceof ArcherClass); // true

const warlock = new WarlockClass('warlie', 100);
console.log(warlock instanceof WarlockClass); // true

Súvisiace články