簡體   English   中英

基於接口TypeScript的通用工廠

[英]Generic factory based on interface TypeScript

我想實現通用方法,該方法將根據提供的接口返回具體類型。 在TypeScript中甚至可能嗎?

這是我的偽示例:

interface IDog {
  canRun: boolean;
}

interface IBird {
  canFly: boolean;
}

class Dog implements IDog {
  canRun: boolean;
}

class Bird implements IBird {
  canFly: boolean;
}

function createInstance<T>(): T {
  const key =  typeof T;

  switch (key) {
    case IBird:
      return new Bird();
     return 
      case IDog:
      return new Dog();
    default:
      break;
  }
}

// concrete is Dog
const concrete = createInstance<IDog>();

createInstance()方法是我要實現的原始示例,它將無法編譯!

我想為createInstance()方法提供接口類型,並實現一些邏輯,這些邏輯將為所提供的接口創建具體的類型。

在TypeScript中可以嗎?

當然,您可以在TypeScript中執行工廠方法。 一種方法:

interface IAnimal {

}

interface IDog extends IAnimal {
    canRun: boolean;
}

interface IBird extends IAnimal {
    canFly: boolean;
}

class Dog implements IDog {
    canRun: boolean;
}

class Bird implements IBird {
    canFly: boolean;
}

class AnimalFactory {
    public static create(animalType: string): IAnimal {
        switch(animalType) {
            case 'dog':
                return new Dog();
            case 'bird':
                return new Bird();
            default:
                throw new Error('Wrong animal type.');
        }
    }
}

const dog: IDog = AnimalFactory.create('dog');
const bird: IBird = AnimalFactory.create('bird');

請注意,工廠隱藏了實際的類名/實現,並通過接口進行操作。 如果願意,可以走得更遠,並使用構建器模式返回與IAnimal界面兼容的動物,例如

case 'dog':
    const dog: IDog = new DogBuilder()
        .setColor('white')
        .setWeight(30)
        .build() // whatever, you get the idea
    return dog;

您將需要使用重載:

function createInstance(key: 'dog'): Dog;
function createInstance(key: 'bird'): Bird;
function createInstance(key: 'dog' | 'bird') {
  // implement
}

然后將密鑰作為參數傳遞

const dog = createInstance('dog'); // typeof dog is Dog

在運行時無法訪問接口,但是可以使用String Literal Types添加類型檢查:

interface IDog {
    canRun: boolean;
}

interface IBird {
    canFly: boolean;
}

class Dog implements IDog {
    canRun: boolean;
}

class Bird implements IBird {
    canFly: boolean;
}

function createInstance(type: 'bird'): Bird;
function createInstance(type: 'dog'): Dog;
function createInstance(type: string): any {
  switch (type) {
    case 'bird':
        return new Bird();
    case 'dog':
        return new Dog();
  }
}

// concrete is Dog
const concrete = createInstance('dog');

我也認為工廠返回類型應該是接口:

function createInstance(type: 'bird'): IBird;
function createInstance(type: 'dog'): IDog;

更新:

另一種方法是存儲對類的引用:

interface IInterfaces {
    dog: IDog;
    bird: IBird;
}

type IFactory<T> = {
    [P in keyof T]: new() => T[P];
}

let factory: IFactory<IInterfaces> = {
    dog: Dog,
    bird: Bird
}

let dog = new factory.dog();

問題在於TS接口在運行時不可用,因此您不能使用JS創建接口。 但! 它們存在於代碼中,因此您可以讀取文件並使用使用文件系統的解決方案來解決此問題。

最近,我發現了這一點: https : //github.com/google/intermock ,這似乎真的很有用。 我還沒有嘗試過,但這是我找到的唯一解決此問題的方法。

node build/src/cli/index.js --files ./example-file.ts --interfaces "Admin"

您選擇接口所在的文件以及要從中創建對象的接口。

您可以在測試之前使用類似husky的命令運行命令,以在實際測試之前生成模擬

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM