IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

TypeScript Discussion :

Typage pour des tableaux de tableaux


Sujet :

TypeScript

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Septembre 2011
    Messages : 21
    Points : 19
    Points
    19
    Par défaut Typage pour des tableaux de tableaux
    Bonjour,

    Le titre de ce ticket n'est pas très évocateur, désolé.

    Je viens de commencer à travailler avec typescript et déjà, première galère dont je ne trouve pas de réponse.

    Alors voilà: Dans un contexte de requêtes/réponses en AJAX, le script client reçoit des données sous la forme d'un objet JSON. Cet objet contient 3 clés associées à trois valeurs:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    type ajaxResponse = {
    call : string,
    status : string,
    datas : any[]
    }
    Et bien sûr, comme vous pouvez vous en douter, le "any[]" pose problème. pour la clé datas, j'attends toujours un tableau. Ce tableau varie en fonction de la réponse du serveur MAIS ces différents tableaux possèdent une structure assez stable et on peut prévoir à l'avance ces différentes structures. Par exemple:
    - Une réponse "Message" du serveur envoie pour "datas" un tableau fixe: ["message" => 'mon message'] que j'ai traduit en { message: string }
    - Une réponse "Redirect" pour rediriger vers une autre page, tableau ['location' => '/otherpage'], structure traduite en ts qui donne { location : string]
    - Une réponse "Errors" qui renvoie les erreurs de saisie d'un formulaire, avec pour datas [ 'errors' => [ 'key1'=> 'val1', 'key2' => 'val2', ...] ]

    Quand le client reçoit la réponse, il donne directement ce tableau datas à un objet dépendant de la valeur de "call". Chacun de ces objets hérite d'une classe abstraite qui prend en paramètre ce fameux tableau "datas". Chaque héritier de cette classe attend le format de tableau qui lui est propre. L'un veut le tableau "message", l'autre veut "location" et le troisième veut ses erreurs à afficher.
    Eh bien j'ai beaucoup de mal à trouver comment remplacer "any[]" (le gros vilain pas beau et incompatible) avec des valeurs admissibles.

    Pensez bien qu'avant de venir poster une telle question, j'ai cherché... Je rappelle que je suis un novice en typescript, ça fait trois jours que je m'y suis mis.
    J'hésite même à laisser tomber typescript pour reprendre mes bonnes vieilles habitudes. Ce serait dommage après tant d'efforts à typer mes codes de manière fiable coté PHP...

    J'ai essayé différentes combinaisons en Union Type mais force est de constater que j'ai encore beaucoup de lacunes. En tout cas, aucune n'est satisfaisante et je patine.

    Merci pour toute réponse apportée.

  2. #2
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Septembre 2011
    Messages : 21
    Points : 19
    Points
    19
    Par défaut on réfléchit, on réfléchit
    Est -ce par hasard ceci ne serait pas un début de solution?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    simpleArray = {
    [ key : string ] : string
    }
     
    errorArray = {
    errors : string[]
    }
     
    ajaxResponse = {
    call : string,
    status : string,
    datas: simpleArray | errorArray
    Ça me parait un peu facile et je ne peux pas tester là tout de suite. Je suis au boulot.

    Vous croyez que ça peut marcher?

  3. #3
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Septembre 2011
    Messages : 21
    Points : 19
    Points
    19
    Par défaut eh ben c'est facile!
    Bonjour toi,

    T'as qu'à faire comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    type ajaxDatas = {
         message?: string,
         location?: string,
         errors?: [ key : string ] : string
    }
     
    type ajaxResponse = {
         call: string,
         datas: ajaxDatas
    }
    C'est con, hein?

  4. #4
    Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2021
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2021
    Messages : 17
    Points : 40
    Points
    40
    Par défaut
    Bonsoir,

    Ta solution ne devrait pas compiler avec un compilateur strict, tu devrais au minimum remplacer errors par errors?: {[ key : string ]: string}. Un outil interessant pour prototyper et tester juste avec un navigateur, le playground officiel Typescript: https://www.typescriptlang.org/play

    Est-il possible d'avoir des retours vide? Par exemple: data: {}. C'est possible avec ton typage.

    Voici une solution fortement typée qui te permettra de découvrir plusieurs choses en Typescript :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    type WithMessage = {
      message: string;
    }
     
    // this is a type guard function, more information
    // here: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
    // and here https://www.typescriptlang.org/docs/handbook/2/classes.html#this-based-type-guards
    // you can write them for WithErrors and WithLocation
    function hasMessage(ajaxData: AjaxData): ajaxData is WithMessage {
      return (ajaxData as WithMessage).message !== undefined;
    }
     
    type WithErrors = {
      errors: Record<string, string>;
    }
     
    type WithLocation = {
      location: string;
    }
     
    function displayMessage(withMessage: WithMessage): void {
      console.log(withMessage); // just an example
    }
     
    function displayErrors(withErrors: WithErrors): void {
      // just an example
      for (const [key, value] of Object.entries(withErrors.errors)) {
        console.log(`error ${key}: ${value}`);
      }
    }
     
    function redirect(withLocation: WithLocation): void {
      window.location.replace(withLocation.location);
    }
     
    type AjaxData = WithMessage | WithLocation | WithErrors; // at least one of them
    // type AjaxData = Partial<WithMessage & WithLocation & WithErrors>; // if an empty result, ie {} is okay
     
    type ajaxResponse = {
      call: string,
      status: string, // number?
      data: AjaxData;
    }
     
    // usage example
    const test: AjaxData = {
      message: "test",
    };
     
    if (hasMessage(test)) {
      displayMessage(test);
    }
    Les types WithMessage, WithErrors et WithLocation peuvent être dans des fichiers séparés, de même que les fonctions relatives à chacun de ces types.

    Si je ne me trompe pas, le [ 'key1'=> 'val1', 'key2' => 'val2', ...] en php est un objet, la représentation d'un objet en typescript se fait à l'aide du type Record (ici: Record<string, string>), plus d'info sur ce type utilitaire ici https://www.typescriptlang.org/docs/...ecordkeys-type.

    PS: data sans s est déjà au pluriel.

    Petite note supplémentaire: tu peux facilement passer le type que tu dois recevoir en paramètre de ta fonction exemple: getAjaxData<T>(/* params */): T { /* appel */ }.
    Ça peut alléger ta base de code.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Septembre 2011
    Messages : 21
    Points : 19
    Points
    19
    Par défaut réponse inattendue
    Bonjour,

    C'est sympa de t'intéresser à la question. Et en plus une réponse sensée et logique et SANS FAUTE D'ORTHOGRAPHE, alors ça c'est chouette et pour le moins original

    En fait, j'ai déjà réglé le problème. Et depuis j'ai même viré les points d'interrogation impliquant un type null. Pas besoin de ça non plus et voilà qui économise quelques lignes de vérifications diverses.

    Et non, pas besoin de vérification: PHP envoie des réponses en JSON mais ça pourrait venir d'un serveur nodejs que ça serait la même chose. Le tableau php renvoyé est json_encodé, si tu me passes l'expression (le franglisme ).

    J'ai aussi fait un brin de ménage dans les réponses possibles. Maintenant la répons n'a plus qu'une seule dimension. Et puis après tout, typescript sait qu'il y aura tels types de données possibles dans la réponse mais n'exige pas que ces données soient effectivement présentes. J'utilise les données ad hoc dans les "Displayers" ad hoc. Du coup, mon objet "ajaxResponse" est plus simple et léger qu'avant et je n'ai plus un objet qui en stocke un autre. Le fait est que j'ai un seul objet qui s'occupe des envois/receptions ajax et plusieurs "Listeners" qui "écoutent" (le plus souvent scotchés à des formulaires), envoient leurs données à l'ajaxHandler, qui a son tour renvoie la réponse au Listener ayant réagi à un évènement et qui ensuite se sert d'un "Displayer" pour gérer la réponse. En gros, on ne peut pas prévoir à l'avance quel Listener va utiliser quel Displayer. Donc le format de réponse doit envisager toutes les possibilités.

    Voilà l'extrait de mon "fichier de déclaration" de types:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    export type ajaxResponse = {
        status: string,                 // trigger callable registered in Displayers storage   (displayer = this.Displayers[status]; displayer->display();)
        message: string,  // controller messages as string
     
        mode: string,               // htmlUpdate : append | prepend | replaceAll | replaceWith | html ...
        node: string,                   // DOM Element containing message
        content : HTMLElement,          // html content to display 
     
        errors: assocArray,          // invalidInputs : controller's errors array
     
        location: string        // new location
    }
    Donc, voilà le problème n'était dû qu'à mon inexpérience et un manque de réflexion.

    Et là, typescript me gonfle. Je voulais tester Vue.js troisième du nom. Ce machin m'a installé une usine à gaz, veut m'obliger à changer toute ma config, se permet même d'écraser mon tsconfig, m'ajoute des fichiers et dossiers par ci par là, et, cerise sur le gateau, il ne trouve même plus les déclarations jquery!!! Et aucun autre moyen d'avoir Vue avec typescript. Alors soit je laisse tomber Vue.js, soit je laisse tomber typescript, soit je vire carrement tout ce qui est node.js et toutes ces joyeusetés... Composer m'a rendu service, malgré là aussi le tas de machins qui arrivent. Et le jour où j'arrive à utiliser les sockets en PHP sans ce machin (quand j'aurais le temps), composer aussi va dégager vite fait!

    Mais je suis H.S.. Même sur son propre post, ça craint. En tout cas, merci d'avoir pris le temps d'une réponse de qualité.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Une technique simple et accessible pour des tableaux responsive
    Par SylvainPV dans le forum Mise en page CSS
    Réponses: 8
    Dernier message: 18/04/2020, 00h21
  2. Réponses: 1
    Dernier message: 02/11/2016, 10h51
  3. Quel logiciel pour des tableaux de bord ?
    Par bebo11 dans le forum Autres produits SAP BO
    Réponses: 4
    Dernier message: 13/04/2010, 22h07
  4. Utilisation des références pour les tableaux
    Par Bouboubou dans le forum Tableaux - Graphiques - Images - Flottants
    Réponses: 4
    Dernier message: 14/12/2005, 14h47
  5. delete[] seulement pour des tableaux d'objets?
    Par Crisanar dans le forum C++
    Réponses: 7
    Dernier message: 22/10/2005, 20h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo