vue.js - Errores de TypeScript al editar componentes antiguos de Vue 3 pero no en los componentes nuevos
Estoy tratando de convertir los scripts de mi componente de página única de Vue 3 para usar TypeScript.
Cuando creo un nuevo componente Test.vue que se ve así, no obtengo errores de TypeScript en mi editor Visual Studio Code:
<script lang="ts">
import { defineComponent, inject, ref } from "vue";
export default defineComponent({
//Some code here
});
</script>
Esto es de esperar porque mi código cumple con la documentación de Vue 3 TypeScript.
Pero cuando convierto mi otro componente existente ExternalApi.vue a lo mismo, estoy viendo errores en defineComponent, inject y ref:
Module '"vue"' has no exported member 'XXXX'. Did you mean to use 'import XXXX from "vue"' instead?Entonces, ¿por qué funciona un componente Test.vue completamente nuevo pero no el componente ExternalApi.vue editado?
Aquí está el componente completo ExternalApi.vue que estoy intentando convertir a 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>
Además de eso, al compilar mediante npm run serve el terminal muestra los mismos errores tanto para Test.vue como para ExternalApi.vue.
Pero no debería mostrar errores en absoluto porque ambos cumplen con la documentación de Vue.
¿Entonces qué está pasando aquí?
ACTUALIZACIÓN :
Esto es lo que contiene mi archivo shims-vue.d.ts. En realidad, no estoy seguro de lo que hace este archivo, pero estaba en el repositorio clonado:
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
Y este es mi archivo package.json:
{
"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"
}
}
Respuesta #1
Pude solucionar estos errores de importación actualizando TypeScript de 3.9.3 a 4.4.4: npm install typescript@latest
Parece que Vue 3.2.0 y versiones posteriores hacen uso de funciones de TS en sus archivos de declaración que requieren una versión actualizada de TypeScript. Esta versión incluye tipos de TypeScript que dependen de Template Literal Types y requiere TS >= 4.1.
¿Por qué la persona que hizo la pregunta se encontró con este problema en su repositorio bifurcado, pero no en el original? Esto se debe a que el repositorio original requería vue ^3.0.0, pero TypeScript ~3.9.3.
Normalmente yarn.lock aseguraría que se instalaran las mismas versiones específicas, pero cuando cambiaron de yarn a npm, el archivo de bloqueo se regeneró, causando un conflicto de versiones cuando se actualizó vue pero no typescript.
¡Este problema es un buen ejemplo de la importancia de los archivos de bloqueo!
Respuesta #2
Este error puede aparecer si estás tratando de usar la API de composición de Vue 3, pero tienes Vue 2 instalado. Actualmente, si ejecutas npm install vue obtendrás la versión 2; necesitas ejecutar npm install vue@next para obtener la versión 3.
Si quieres usar la versión 2, el enfoque básico de TypeScript para la definición de componentes es en cambio así:
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
// type inference enabled
})
</script>
Recomiendo probar vue-class-component y vue-property-decorator si quieres usar TypeScript con Vue 2, ¡son realmente geniales!
