2017-09-29 2 views
1

Ich möchte generische Methode implementieren, die konkrete Art basierend auf bereitgestellten Schnittstelle zurückgeben wird. Ist das in TypeScript überhaupt möglich?Generische Fabrik basierend auf Schnittstelle TypeScript

Hier mein Pseudo-Beispiel ist:

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() Methode ist ein rohes Beispiel dafür, was ich zu erreichen versuchen, es wird nicht kompilieren!

Ich möchte Schnittstelle Typ Methode zur Verfügung stellen und einige Logik implementieren, die konkreten Typ für die bereitgestellte Schnittstelle erstellen wird.

Ist es in TypeScript möglich?

+0

Would Bereitstellung type through string Argument wäre akzeptabel? Ich meine etwas wie 'createInstance (animalType: string)'. – kamyl

+0

In diesem Fall wird "Beton" nicht eingegeben. Leider versuche ich einen geeigneteren Ansatz zu finden. – kat1330

+0

Alles würde getippt werden. Sie könnten mit etwas wie 'const Hund: IDog = AnimalFactory.create ('Hund');' – kamyl

Antwort

0

Schnittstellen sind im laufenden Betrieb nicht zugänglich, aber Sie können mit String Literal Types Typ Überprüfung hinzufügen:

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'); 

Auch ich denke, die Fabrik Rückgabetyp Schnittstelle sein sollte:

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

Update:

Die Alternative ist, Verweise auf Klassen zu speichern:

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(); 
+0

Wenn er bereit ist, Klassen anstelle von Schnittstellen zu verwenden, dann wäre es ohne die Verwendung von Zeichenfolgen möglich. Er müsste die Klasse als Parameter übergeben und den Klassennamen einschalten. –

+0

Ich denke, der Typ, der von der Fabrik zurückgegeben wird, sollte Schnittstelle sein, nicht Klasse. Es ist nicht sinnvoll, die Klasse zu übergeben, um eine Klasse zu erstellen. Dafür können Sie den 'neuen' Operator verwenden. – Artem

1

Natürlich können Sie eine Factory-Methode in TypeScript ausführen. Ein Weg, es zu tun:

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'); 

Beachten Sie, dass die Fabrik tatsächliche Klassennamen/Implementierungen versteckt und über Schnittstellen funktioniert. Sie können sogar noch weiter gehen, wenn Sie möchten und Erbauer verwenden, um Ihre Tiere kompatibel mit IAnimal Schnittstelle zurückkehren, wie

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

Sie müssen Überlastungen verwenden:

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

Dann den Schlüssel übergeben als Parameter

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