2017-08-24 4 views
1

Je voudrais créer une interface qui définisse un ensemble de pares de valeur de clé où la valeur est restreinte à un type de classeWhichExtendsSpecificSuperClass.Restreindre le type par superclasse dans l'interface

Par exemple, cette interface:

interface MyInterface { 
    key: typeof SuperClass 
} 

et cette classe de base:

class BaseClass extends SuperClass {...} 

appliquée de cette manière:

function myFunction(arg: MyInterface) {...}; 

myFunction({ 
    key: BaseClass 
}); 

Le code ci-dessus me disait que typeof BaseClass n'est pas assignable à typeof SuperClass.

Maintenant je comprends que ce que je fais n'est pas correct, mais est-ce possible d'une autre façon? Je voudrais m'assurer que les seules valeurs permises pour "key" sont des classes de type qui étendent SuperClass? Si j'avais affaire à des fonctions, je pourrais utiliser des génériques, mais pour autant que je sache, il n'y a aucun moyen d'exprimer un générique à la propriété de l'objet.

Toute aide serait géniale!

+0

Vous ne savez pas quel est le problème, le code suivant fonctionne pour moi classe SuperClass { nr: nombre; } Interface MyInterface { clé: typeof SuperClass } classe BaseClass étend superclasse { s: string; Fonction myFunction (arg: MyInterface) { var c = new arg.key(); MyFunction ({ key: BaseClass }); –

+0

Quelle version de tapuscrit utilisez-vous? J'ai eu cette compilation et s'est éloigné du projet et maintenant il semble avoir un problème. – Jeremythuff

+0

J'utilise 2.4.2 –

Répondre

1

Si toutes les classes qui s'étendent SuperClass ont des paramètres de constructeur compatibles, votre code devrait fonctionner sans erreur. Par exemple:

class SuperClass { 
    superValue: string; 
} 
interface MyInterface { 
    key: typeof SuperClass 
} 
class BaseClass extends SuperClass { 
    baseValue: string; 
} 
function myFunction(arg: MyInterface) { }; 
myFunction({ 
    key: BaseClass // no error 
}); 

Il n'y a aucun problème ici parce que les deux BaseClass et SuperClass peuvent être construits avec des arguments zéro. Mais si vous changez le constructeur de BaseClass:

class BaseClass extends SuperClass { 
    baseValue: string; 
    constructor(someArgument: string) { 
    super(); 
    } 
} 

vous obtiendrez l'erreur que vous avez mentionné lorsque vous appelez myFunction():

 
Argument of type '{ key: typeof BaseClass; }' is not assignable to parameter of type 'MyInterface'. 
    Types of property 'key' are incompatible. 
    Type 'typeof BaseClass' is not assignable to type 'typeof SuperClass'. 

Maintenant, en fonction de ce que vous voulez faire avec MyInterface, cette erreur pourrait être important. Avez-vous l'intention de prendre la propriété key de la valeur MyInterface et de l'utiliser pour construire une instance de certaines sous-classes de SuperClass? Par exemple:

declare let myInterface: MyInterface; 
let someInstance = new myInterface.key(); 

Si oui, alors vous devez vous assurer que le constructeur de la classe accepte le bon nombre et le type d'arguments, et cette erreur est de vous aider. Il vous dit de changer le constructeur BaseClass pour qu'il soit compatible avec le constructeur de SuperClass. Par exemple, si nous faisons someArgument en option:

class BaseClass extends SuperClass { 
    baseValue: string; 
    constructor(someArgument?: string) { 
    super(); 
    } 
} 

alors l'erreur disparaît parce que new SubClass() va maintenant travailler sans argument.


Si vous ne pas l'intention d'utiliser MyInterface pour construire des instances, et vous ne se soucient pas sur le nombre et le type d'arguments que les constructeurs prennent, et que vous voulez juste de tenir un constructeur de classe pour une raison quelconque ...alors vous pouvez le faire:

type Constructor<T> = { 
    new(...args: any[]): T; // any number and type of arguments 
} 
interface MyInterface { 
    key: Constructor<SuperClass> 
} 

Maintenant myFunction() fonctionnera même si les signatures du constructeur sont incompatibles. C'est parce que vous ne voulez pas vraiment vous limiter à typeof SuperClass; vous souhaitez accepter un constructeur qui crée un SuperClass, et c'est ce que signifie Constructor<SuperClass>. Donc l'erreur disparaît et vous êtes heureux.


Espérons que l'une de ces deux solutions fonctionnera pour vous. Bonne chance!