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
CharacterOptionsbudem 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
