[英]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.