vue.js - Hvordan opprettholde korrekt TypeScript-type på Vue-komponentdata?


Jeg jobber med et Vue-prosjekt som jeg oppdaterer til Vue 3 med TypeScript. Jeg har funnet en merkelig oppførsel med TypeScript-parsere/kompilatoren. Jeg har følgende komponent:

    export default defineComponent({
        name: 'Test',

        data() {
            return {
                test: new Child(),
            };
        },
        
        methods: {
            testMethod: function () {
                this.test = new Child(); 
                let test2 = new Child();
            }
        },
    });


    class Child {
        b = 0;
    }

I metoden tror parseren at test2 er av typen Child. Men den tror at this.test er av typen {b: number} (dvs. den har mistet forbindelsen til Child). Å holde musepekeren over datastrukturen (vscode) viser at når den opprettes der, tror den at typen er Child.

I dette eksemplet er det egentlig ikke et problem fordi det enkelt kan kaste det. Men hvis Child i stedet er definert som:

  class Parent {
     private a = 1;
  }
  class Child extends Parent {
     b = 0;
  }

da har this.test fortsatt samme type {b:number} (det mister det private medlemmet) og kan ikke lenger kastes til Parent. Dette fører til endeløs typecasting til any for å omgå problemet. Et annet symptom på at den ikke henter riktig type, er at noe som this.test.a=3 genererer property does not exist (ts2339), mens test2.a=3; genererer property is private and only accessible with parent (ts2341) (som er den riktige feilen).

Jeg har også prøvd å spesifisere returtypen til data() manuelt, med samme resultat.

Gjør jeg noe galt? Er dette bare hvordan Vue-pluginen fungerer med Typescript?

Svar #1

Som beskrevet her, er problemet at data-elementene er reaktive, og i innpakningen/utpakking mister klassen.

Løsningen der indikerer at det er anbefalt å bruke en shallowRef() (fordi det generelt er foretrukket å holde instansen rå for noe så komplekst):

export default defineComponent({
        name: 'Test',

        setup() {
            return {
                test: shallowRef(new Child()),
            };
        },

      ...
        
    });

Hvis du ikke har noe imot (eller foretrekker) wrapperen, vil det å bare endre data til setup løse skriveproblemet:

export default defineComponent({
        name: 'Test',

        setup() {
            return {
                test: new Child(),
            };
        },
        
        ...
    });

Relaterte artikler