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

Relaterte artikler