导出类的变体

时间:2019-04-21 14:00:43

标签: javascript typescript

我正在尝试导出我想导入其他地方的类的某些变体。 我不知道没有实例化就可以创建它们吗? 以及我该怎么做。

这就是我现在拥有的

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

我希望能够在 index.ts 文件

中执行类似的操作
import { Character } from './Character';
import { ArcherOptions, WarlockOptions } from './CharacterOptions';

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

就像动态创建(通过someWrapperOfCharacter())我可以公开的新特定类。

我知道我可以直接创建扩展Character的类,但是我尝试避免这种情况,因为:

  • 我不知道将来会有多少CharacterOptions
  • 我不想每次我想添加新的CharacterOptions
  • 时都不必创建新的变体
  • 我想允许通过传递扩展CharacterOptions的自定义对象来直接创建自定义类

2 个答案:

答案 0 :(得分:2)

您可以将选项的构造函数传递给该类,并具有一个函数,该函数创建将选项类设置为特定实现的派生类型:

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>

答案 1 :(得分:0)

我尝试过提香的回答,但并没有完全满足我(尽管它对我有很大帮助)。

我终于这样写了包装器:

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