2019 es el año de Typescript, dos de los tres frameworks más populares de JavaScript han empezado a utilizar este superset de tipado, dichos frameworks son: React y Vue. En el caso de Facebook (React) logramos ver desde el repositorio de Github de React como aceptaban un Pull Request para utilizar dicha herramienta:
https://twitter.com/mohsen____/status/1085396444201275392
Y en el caso de Vue pudimos observar recientemente que el mismo creador del framework; Evan You, ha optado por utilizar Typescript:
Ironicamente pienso que TypeScript me ha ayudado a evitar las clases en lugar de utilizarlos. Vue 3 tiene como código base 100% de Typescript con 0 usos de clases
- https://twitter.com/youyuxi/status/1175433025179529216
Te preguntarás, ¿por qué utilizar Typescript en un proyecto de Vue?
Ahora queda la siguiente pregunta, ¿cómo puedo crear un proyecto de Vue con TypeScript? Tenemos las siguientes dos opciones:
Utilizando Vue-Cli
Si deseas crear un proyecto nuevo sin muchas preocupaciones de configuración, tenemos el CLI (Console Line Interface) de Vue, la cual nos permite seleccionar que tipo de proyecto queremos, y entre sus opciones crear la instalación y configuración necesaria para que Vue funcioné con Typescript. Para ello abrimos la consola de comandos de tu preferencia y nos aseguramos que tenemos VueCLI instalado:
vue
Este comando nos mostrará diferentes opciones que podemos utilizar con el CLI, en caso de que al escribir te sale un error de que Vue no es reconocido, procedemos a realizar la instalación del CLI con el comando:
npm i -g @vue/cli
Una vez que se ha realizado la instalación, corroboramos que tenemos el CLI de Vue instalado con el comando vue que utilizamos previamente. Teniendo instalada la herramienta utilizamos el comando: vue create mi-proyecto-vue-typescript
, la cual nos irá dando las siguientes opciones para crear el proyecto:
Seleccionamos Manually select features (Elegir características manualmente)
A continuación nos mostrará un menú de opciones que tenemos para la creación del proyecto, para navegar utilizamos nuestras teclas de flechas (arriba y abajo) y para seleccionar presionaremos la barra espaciadora o espacio. Para nuestro ejemplo seleccionamos únicamente Typescript, por lo que nuestra selección deberá quedar así y presionamos Enter:
En seguida nos preguntará si queremos utilizar una sintaxis de componentes de clase-estilo (class-style component). De acuerdo a la documentación de Vue, nos recomiendan que utilicemos la opción Vue.extend, por lo que esta vez le diremos que no:
Nos preguntará que si queremos utilizar Babel con TypeScript, le diremos que sí para que nuestro proyecto sea compatible con navegadores como Internet Explorer:
Seleccionamos TSLint como linter:
Seleccionamos Lintear al guardar (Lint on save):
Elegimos guardar las configuraciones en un archivo especializado para cada uno (Babel, ESLint, TSLint, etc)
Y en caso de que quieras guardar la configuración que hemos realizado escribimos y y escribimos el nombre de nuestro preset, en este caso diré que sí y le pondremos my-ts-vue-preset
, después esperamos un momento en lo que NPM realiza la instalación de dependencias de nuestro proyecto:
Una vez terminada la instalación, abrimos nuestro proyecto en nuestro editor de texto favorito y tendemos el siguiente orden de archivos de Vue + Typescript listo para desarrollo:
A tráves de Webpack
Si deseas empezar el proyecto desde cero debemos utilizar Webpack, para ello realizamos los siguientes comandos:
npm init -y //Inicializamos un proyecto de npm, con el flag -y le decimos a todo que sí
npm i -D webpack webpack-cli webpack-dev-server
Añadiendo Typescript y Vue
Para que nuestro proyecto pueda utilizar nuestras dos herramientas de este tutorial, necesitaremos de las siguientes dependencias:
npm i -D vue vue-template-compiler vue-loader babel-loader @vue/babel-preset-app
@babel/core @babel/plugin-proposal-class-properties @babel/plugin-syntax-dynamic-import@babel/preset-env typescript ts-loader
No olvidemos que debemos añadir un linter para que nos observe nuestros posibles problemas en el código:
npm i -D eslint eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise
@typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-standard eslint-plugin-vue tslint
Una vez terminado, entramos a nuestro editor de texto y creamos nuestro webpack.config.js de la siguiente manera:
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
app: path.resolve(__dirname, 'src/index.ts')
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].js',
publicPath: '/'
},
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
},
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
},
// Añadimos este loader para que TypeScript funcione dentro de nuestro componente .vue
{
test: /\.ts$/,
loader: 'ts-loader',
options: { appendTsSuffixTo: [/\.vue$/] }
}
]
},
plugins: [
new VueLoaderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/index.html')
})
]
}
Añadimos los archivos .babelrc, eslinterc.js tsconfig.json y tslint.json
.babelrc
{
"presets": [
"@vue/app"
]
}
.eslintrc.js
module.exports = {
env: {
browser: true,
es6: true
},
extends: [
'plugin:vue/essential',
'standard'
],
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly'
},
parserOptions: {
ecmaVersion: 2018,
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
plugins: [
'vue',
'@typescript-eslint'
],
rules: {
}
}
tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
tslint.json
{
"defaultSeverity": "warning",
"extends": [
"tslint:recommended"
],
"linterOptions": {
"exclude": [
"node_modules/**"
]
},
"rules": {
"indent": [true, "spaces", 2],
"interface-name": false,
"no-consecutive-blank-lines": false,
"object-literal-sort-keys": false,
"ordered-imports": false,
"quotemark": [true, "single"]
}
}
No olvidemos que debemos de tener una estructura de archivos similar a nuestra contra parte de Vue CLI, por lo que la estructura de archivos deberá quedar de la siguiente manera:
Antes de finalizar nuestro tutorial de webpack debemos añadir dos archivos, que como habrás visto dentro de la imagen anterior, son los archivos: index.ts y shims-vue.ts dentro de la carpeta src, e index.html dentro de public, la cual deberán quedar:
index.ts - Al igual que nuestra contra parte
import Vue from 'vue';
import App from './App.vue';
new Vue({
render: (h) => h(App),
}).$mount('#app');
shims-vue.d.ts - Aquí le decimos a TypeScript que reconozca nuestros archivos Vue
declare module'*.vue' {
import Vue from'vue';
exportdefault Vue;
}
public/index.html - Aquí agregamos donde se asignará donde Vue cargará los componentes que vayamos a necesitar:
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><metahttp-equiv="X-UA-Compatible"content="ie=edge"><title>Mi Proyecto Vue + TypeScript + Webpack</title></head><body><divid="app"></div></body></html>
Para finalizar solo añadimos el comando en la sección de scripts a package.json:
"scripts": {
"serve": "webpack-dev-server --config ./webpack.config.js --hot"
}
Si quieres consultar el tutorial de Webpack puedes visitar el repositorio de GitHub:
https://github.com/manuelojeda/vue-typescript-webpack-template