vue.js - TypeScript-feil når du redigerer gamle Vue 3-komponenter, men ikke på nye komponenter
Jeg prøver å konvertere skriptene i min Vue 3 en-sides komponent til å bruke TypeScript.
Når jeg lager en helt ny Test.vue-komponent som ser slik ut, får jeg ingen TypeScript-feil i Visual Studio Code-redigeringsprogrammet mitt:
<script lang="ts">
import { defineComponent, inject, ref } from "vue";
export default defineComponent({
//Some code here
});
</script>
Dette er som forventet fordi koden min følger Vue 3 TypeScript-dokumentasjonen.
Men når jeg konverterer min andre eksisterende ExternalApi.vue-komponent til det samme, ser jeg feil på defineComponent, inject og ref:
Module '"vue"' has no exported member 'XXXX'. Did you mean to use 'import XXXX from "vue"' instead?Så hvorfor fungerer en helt ny Test.vue-komponent, men ikke den redigerte ExternalApi.vue-komponenten?
Her er den fullstendige ExternalApi.vue-komponenten jeg prøver å konvertere til TypeScript:
<template>
<div>
<div class="mb-5">
<h1>External API</h1>
<p>
Call Fauna.
</p>
<button class="btn btn-primary m-5" @click.prevent="callApi">
Call API
</button>
<label for="product-name">Product Name:</label>
<input
type="text"
v-model="productValue"
id="product-name"
name="product-name"
/><br /><br />
<button class="btn btn-primary m-5" @click.prevent="createProduct">
Create Product
</button>
</div>
<div class="result-block-container">
<div :class="['result-block', executed ? 'show' : '']">
<h6 class="muted">Result</h6>
{{ JSON.stringify(apiMessage, null, 2) }}
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, inject, ref } from "vue";
import { query as q, Client } from "faunadb";
export default defineComponent({
name: "Api",
setup() {
let productValue = ref("");
let apiMessage = ref(null);
let executed = ref(false);
const auth = inject("Auth");
const callApi = async () => {
const accessToken = await auth.getTokenSilently();
try {
const client = new Client({
secret: accessToken,
domain: "db.us.fauna.com",
port: 443,
scheme: "https",
});
const { Paginate, Documents, Collection } = q;
const data = await client.query(
Paginate(Documents(Collection("products")))
);
console.log(accessToken);
console.log(data);
apiMessage.value = data;
executed.value = true;
} catch (e) {
console.log(e);
apiMessage = `Error: the server responded with '${e.response.status}: ${e.response.statusText}'`;
}
};
const createProduct = async () => {
const accessToken = await auth.getTokenSilently();
try {
const client = new Client({
secret: accessToken,
domain: "db.us.fauna.com",
port: 443,
scheme: "https",
});
const { Create, Collection, CurrentIdentity } = q;
const data = await client.query(
Create(Collection("products"), {
data: {
name: productValue.value,
owner: CurrentIdentity(),
},
})
);
console.log("productValue data", data);
} catch (e) {
console.log(e);
apiMessage = `Error: the server responded with '${e.response.status}: ${e.response.statusText}'`;
}
};
return {
callApi,
createProduct,
apiMessage,
executed,
productValue,
};
},
});
</script>
I tillegg, når man kompilerer via npm run serve viser terminalen de samme feilene for både Test.vue og ExternalApi.vue.
Men det skal ikke vises noen feil i det hele tatt fordi begge følger Vue-dokumentasjonen.
Så hva foregår her?
OPPDATERING :
Dette er hva filen min shims-vue.d.ts inneholder. Jeg er egentlig ikke sikker på hva denne filen gjør, men den var i det klonede repoet:
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
Og dette er min package.json-fil:
{
"name": "replicator",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --port 3000",
"build": "vue-cli-service build"
},
"dependencies": {
"@auth0/auth0-spa-js": "^1.13.6",
"@fortawesome/fontawesome-svg-core": "^1.2.32",
"@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/vue-fontawesome": "3.0.0-3",
"ansi-html": "^0.0.7",
"axios": "^0.21.1",
"core-js": "^3.6.5",
"element-plus": "^1.0.2-beta.28",
"faunadb": "^4.4.1",
"glob-parent": "^6.0.2",
"set-value": "^4.1.0",
"vue": "^3.2.20",
"vue-router": "^4.0.11",
"vue-template-compiler": "^2.6.14",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.13",
"@vue/cli-plugin-router": "4.5.13",
"@vue/cli-plugin-typescript": "^4.5.13",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "^4.5.13",
"@vue/compiler-sfc": "^3.0.0",
"sass": "^1.32.7",
"sass-loader": "7.3.1",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"typescript": "~3.9.3",
"vue-cli-plugin-element-plus": "~0.0.13"
}
}
Svar #1
Jeg klarte å fikse disse importfeilene ved å oppgradere TypeScript fra 3.9.3 til 4.4.4: npm install typescript@latest
Det ser ut til at Vue 3.2.0 og nyere bruker TS-funksjoner i deklarasjonsfilene sine som krever en oppgradert TypeScript. Denne utgivelsen leverer TypeScript-typinger som er avhengige av Template Literal Types og krever TS >= 4.1.
Hvorfor støtte spørsmålstiller på dette problemet i deres forkede repo, men ikke i det originale? Dette er fordi det originale repoet krevde vue ^3.0.0, men TypeScript ~3.9.3.
Normalt ville yarn.lock sikre at de samme spesifikke versjonene ble installert, men da de byttet fra yarn til npm, ble låsefilen generert på nytt, noe som forårsaket en versjonskonflikt da vue ble oppgradert, men ikke typescript.
Dette problemet er et godt eksempel på viktigheten av låsefiler!
Svar #2
Denne feilen kan oppstå hvis du prøver å bruke Vue 3 composition API, men du har Vue 2 installert. For øyeblikket, hvis du kjører npm install vue, får du versjon 2; du må kjøre npm install vue@next for å få versjon 3.
Hvis du vil bruke versjon 2, er den grunnleggende TypeScript-tilnærmingen for komponentdefinisjon i stedet slik:
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
// type inference enabled
})
</script>
Jeg anbefaler å prøve vue-class-component og vue-property-decorator hvis du vil bruke TypeScript med Vue 2, de er virkelig flotte!
