Generisk fabrikk basert på grensesnitt TypeScript
Jeg vil implementere en generell metode som vil returnere en konkret type basert på den oppgitte grensesnittet. Er dette overhodet mulig i TypeScript?
Her er mitt pseudoeksempel:
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()-metoden er et rått eksempel på det jeg prøver å oppnå, den vil ikke kompilere!
Jeg vil gjerne gi en grensesnittstype til createInstance()-metoden og implementere noe logikk som vil opprette en konkret type for det angitte grensesnittet.
Er det mulig i TypeScript?
Svar #1
Grensesnitt er ikke tilgjengelige under kjøring, men du kan legge til typsjekking ved å bruke tekstlige typelitteraler:
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');
Jeg tror også at fabrikkens returtype bør være grensesnitt:
function createInstance(type: 'bird'): IBird;
function createInstance(type: 'dog'): IDog;
Oppdatering:
Alternativet er å lagre referanser til klasser:
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();
Svar #2
Du vil måtte bruke overbelastninger:
function createInstance(key: 'dog'): Dog;
function createInstance(key: 'bird'): Bird;
function createInstance(key: 'dog' | 'bird') {
// implement
}
Deretter send nøkkelen som en parameter
const dog = createInstance('dog'); // typeof dog is Dog
