récupérer le type déclaré

a marqué ce sujet comme résolu.

Bonjour à toutes et tous,

J’ai découvert TypeScript avec Angular 2 et je dois dire que je suis assez conquis par les possibilités offerte par cette surcouche.
Je suis néanmoins bloqué, je suis en train de développé un ORM et je bloque lorsque je dois récupérer l’objet opposé de la relation.

Concrètement, à un moment il faut que je crée une nouvelle instance de l’objet que je vais ensuite hydrater… sauf que je n’y arrive pas.

Si je tente de faire

1
2
3
function hydrate(modelName: string) {
  let model = new modelName;
}

J’ai droit à une erreur me disant que modelName n’est pas un constructeur.

J’ai essayé dans la déclaration de mon modèle de mettre la classe directement plutôt qu’une chaine:

1
2
3
4
class Foo {
  @ManyToOne(Bar)
  model: Bar;
}

Mais j’ai une erreur à l’execution me signalant que Bar n’existe pas. (au moment de l’analyse de la déclaration de la classe)

Ma dernière idée en date est de récupérer le type déclarer dans la classe, si je peux savoir que model est Bar et ce même si la valeur actuelle ne l’est pas (typiquement null ou undefined) alors sa m’arrangerai.

Sauf que je n’ai rien trouver me permettant d’arriver à ce résultat.

J’ai également recherché sur Google comment instancier une nouvelle classe dynamique (ma première technique), je suis tombé sur des résultat à base de this[className] ou window, rien ne fonctionne :(

Merci d’avance pour votre aide.
Cordialement, La source.

+0 -0

Je comprend le problème… n’empêche que j’aimerai pouvoir dynamiquement instancier une classe, sous-entendu dont le type n’est pas connu autrement que via la chaîne de caractère.

En php c’est parfaitement faisable en faisant $class = 'Foo'; $objet = new $class();, j’aurai espéré quelque chose permettant d’arriver au même résultat.

+0 -0

Mais pourquoi tu passes une string et pas simplement ton prototype ?

1
2
3
4
5
6
7
8
function Point(x, y) {
  this.x = x;
  this.y = y;
}

function getInstance(proto, ...args) { return new proto(...args); }

const p1 = getInstance(Point, 13, 37); // -> Point {x: 13, y: 37}
+1 -0

C’est ce que j’ai essayé dans mon deuxième exemple.

Comme je l’ai dis je développe un ORM, du point de vue utilisation pour dire à l’ORM de suivre une propriété on ajoute un décorateur. Dans ce décorateur on peu donner des options. Une chaine sa passe nickel mais un prototype… le problème est qu’il ne le connais pas encore au moment de l’évaluation du décorateur.

+0 -0

Pourquoi… c’est une bonne question, j’ignore comment javascript fait pour évaluer les expression… n’empêche que ce code ne fonctionne pas.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import {OneToMany, ManyToOne, Model, Collection} from "./Data.service";

@Model
export class Foo
{
    @OneToMany(Bar)
    bars: Collection<Bar>;
}

@Model
export class Bar
{
    @ManyToOne(Foo)
    foo: Foo;
}

J’ai l’erreur

models.ts:7Uncaught ReferenceError: Bar is not defined

Et j’ai l’erreur vraiment à l’initialisation du projet… j’en conclus donc qu’au moment de l’évaluation Bar n’existe réellement pas… s’pas totalement faux vu qu’il est déclarer un peu plus bas, n’empêche que comme les classes se font références mutuellement…

D’où mon idée de passer l’information sous forme de chaine, au moment ou on va vraiment l’utiliser là la classe Bar aura bel et bien été déclarée du coup pas de soucis.

+0 -0

Un décorateur c’est une fonction appelée à la déclaration; concrètement avec mes décorateurs je redéfini les propriétés sur lesquels ils sont placé de façon à intercepter les accès et modifications. Dans la base de données je stocke une référence, lorsque je tente d’accéder à la propriété je transforme la référence en l’objet sur laquelle elle pointe.
Et au moment de la sauvegarde je transforme l’objet en une référence.

Faire cela via le décorateur rend la définition du modèle nettement plus élégante.

Le truc c’est qu’à l’utilisation je tente d’accéder à la propriété je dois retourner un objet du type de la propriété (si je dis que ma propriété est de type Bar il faut que je récupère bel et bien un Bar), je dois donc en instancier un nouveau. Sauf que comme le code du décorateur est générique, il me faut bien une façon de savoir que c’est un Bar pour cette propriété, un Foo pour une autre et ainsi de suite.

+0 -0

Non mais je sais ce qu’est un décorateur, ma question c’est quel est le javascript généré derrière parce que vraiment il devrait pas y avoir de problème ici.

Tu utilises bar dans foo, bar n’a pas besoin d’être déclaré avant la déclaration du prototype foo…

+0 -0

Comme je l’ai dit, je redéfini la propriété en assesseur et je définit une nouvelle propriété stockant la valeur réelle. C’est tout.

Il est à noté que mon IDE ne me rouspette pas dessus (alors qu’il à tendance à souvent me rouspetté dessus ^^ ). C’est mon navigateur (Google Chrome en l’occurence, mais je viens d’essayé avec Firefox c’est pareil, bien que l’erreur est différente ReferenceError: can't access lexical declaration 'Bar' before initialization main.bundle.js:55274:5) qui me rouspette dessus dés la déclaration.

+0 -0

Oui oui, et comme tu peux le voir, l’erreur est à la ligne 55.274, je vais donc pas filé l’ensemble de ces lignes sa sera juste imbuvable…

voici un petit morceau (autour de la ligne 55.274

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
let Foo = class Foo {
};
__decorate([
    __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__Data_service__["a" /* OneToMany */])(Bar), 
    __metadata('design:type', (typeof (_a = typeof __WEBPACK_IMPORTED_MODULE_0__Data_service__["b" /* Collection */] !== 'undefined' && __WEBPACK_IMPORTED_MODULE_0__Data_service__["b" /* Collection */]) === 'function' && _a) || Object)
], Foo.prototype, void 0);
Foo = __decorate([
    __WEBPACK_IMPORTED_MODULE_0__Data_service__["c" /* Model */], 
    __metadata('design:paramtypes', [])
], Foo);
let Bar = class Bar {
};
+0 -0

Du coup __decorate ne se passe pas dans le prototype de Foo, il y ajoute des trucs plus tard.

Tu peux donc faire ça après avoir déclaré Bar, ou effectivement passer une string mais seulement à condition que le contenu du décorateur ne soit pas évalué avant la déclaration de Bar.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte