默认情况下,TypeScript 支持不会添加到您的项目中(除非您在创建项目文件夹时选择了 TS),但可以通过遵循此页面上的指南轻松集成。
提示
以下步骤仅在您**未**在创建新的 Quasar 项目时选择 TypeScript 支持时才需要。如果您在项目创建时选择了 TS 选项,则 TypeScript 支持已启用。
安装 TypeScript 支持
在项目的根目录下创建/tsconfig.json
文件,内容如下:
{
"extends": "@quasar/app-vite/tsconfig-preset",
"compilerOptions": {
// `baseUrl` should be set to the current folder to allow Quasar TypeScript preset to manage paths on your behalf
"baseUrl": "."
},
"exclude": [
"./dist",
"./.quasar",
"./node_modules",
"./src-capacitor",
"./src-cordova",
"./quasar.config.*.temporary.compiled*"
]
}
然后安装typescript
包
$ yarn add --dev typescript
现在您可以开始在项目中使用 TypeScript 了。请注意,某些 IDE 可能需要重新启动才能使新设置完全生效。
提示
请记住,您必须将 JavaScript 文件的扩展名更改为.ts
才能在其中编写 TypeScript 代码。要向组件中写入 TS 代码,请更改脚本开头标签,如下所示<script lang="ts">
。
警告
如果您未能添加tsconfig.json
文件,则应用程序将在编译时中断!
Linting 设置
提示
由于类型检查开销,TypeScript Linting 非常慢,建议您在/quasar.config
文件中禁用开发构建的 Linting。
首先添加必要的依赖项
$ yarn add --dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
# you might also want to install the `eslint-plugin-vue` package.
然后根据需要更新您的 ESLint 配置,例如以下示例
const { resolve } = require('node:path');
module.exports = {
// https://eslint.org.cn/docs/user-guide/configuring#configuration-cascading-and-hierarchy
// This option interrupts the configuration hierarchy at this file
// Remove this if you have an higher level ESLint config file (it usually happens into a monorepos)
root: true,
// https://eslint.vuejs.ac.cn/user-guide/#how-to-use-custom-parser
// Must use parserOptions instead of "parser" to allow vue-eslint-parser to keep working
// `parser: 'vue-eslint-parser'` is already included with any 'plugin:vue/**' config and should be omitted
parserOptions: {
// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#configuration
// https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#eslint
// Needed to make the parser take into account 'vue' files
extraFileExtensions: ['.vue'],
parser: '@typescript-eslint/parser',
project: resolve(__dirname, './tsconfig.json'),
tsconfigRootDir: __dirname,
ecmaVersion: 2021, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports
},
// Rules order is important, please avoid shuffling them
extends: [
// Base ESLint recommended rules
'eslint:recommended',
// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage
// ESLint typescript rules
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
// consider disabling this class of rules if linting takes too long
'plugin:@typescript-eslint/recommended-requiring-type-checking',
// https://eslint.vuejs.ac.cn/rules/#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules
'plugin:vue/essential',
// --- ONLY WHEN USING PRETTIER ---
// https://github.com/prettier/eslint-config-prettier#installation
// usage with Prettier, provided by 'eslint-config-prettier'.
'prettier',
'prettier/@typescript-eslint',
'prettier/vue',
],
plugins: [
// required to apply rules which need type information
'@typescript-eslint',
// https://eslint.vuejs.ac.cn/user-guide/#why-doesn-t-it-work-on-vue-file
// required to lint *.vue files
'vue',
],
// add your custom rules here
rules: {
// others rules...
// TypeScript
'quotes': ['warn', 'single'],
// this rule, if on, would require explicit return type on the `render` function
'@typescript-eslint/explicit-function-return-type': 'off',
// in plain CommonJS modules, you can't use `import foo = require('foo')` to pass this rule, so it has to be disabled
'@typescript-eslint/no-var-requires': 'off',
}
}
如果出现任何错误,请阅读typescript-eslint 指南,此示例基于该指南。
最后一步,更新您的yarn lint
命令以同时 lint .ts
文件。
最后,编辑您的/quasar.config
文件
eslint: {
// fix: true,
// include: [],
// exclude: [],
// rawOptions: {},
warnings: true,
errors: true
},
TypeScript 声明文件
如果您在搭建项目时选择了 TypeScript 支持,则会自动为您搭建这些声明文件。如果在项目创建期间未启用 TypeScript 支持,请创建以下文件。
/* eslint-disable */
/// <reference types="vite/client" />
// Mocks all files ending in `.vue` showing them as plain Vue instances
declare module '*.vue' {
import type { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any>;
export default component;
}
/* eslint-disable */
// Forces TS to apply `@quasar/app-vite` augmentations of `quasar` package
// Removing this would break `quasar/wrappers` imports as those typings are declared
// into `@quasar/app-vite`
// As a side effect, since `@quasar/app-vite` reference `quasar` to augment it,
// this declaration also apply `quasar` own
// augmentations (eg. adds `$q` into Vue component context)
/// <reference types="@quasar/app-vite" />
/* eslint-disable */
declare namespace NodeJS {
interface ProcessEnv {
NODE_ENV: string;
VUE_ROUTER_MODE: 'hash' | 'history' | 'abstract' | undefined;
VUE_ROUTER_BASE: string | undefined;
// Define any custom env variables you have here, if you wish
}
}
根据您正在使用的功能和构建模式,请参阅以下部分。
Pinia
如果您正在使用Pinia,请将以下部分添加到您的项目中。Quasar CLI 提供router
属性,如果您有其他全局属性,则可能需要添加更多属性。
import { Router } from 'vue-router';
/*
* When adding new properties to stores, you should also
* extend the `PiniaCustomProperties` interface.
* @see https://pinia.vuejs.ac.cn/core-concepts/plugins.html#typing-new-store-properties
*/
declare module 'pinia' {
export interface PiniaCustomProperties {
readonly router: Router;
}
}
Vuex
如果您正在使用Vuex,请将以下部分添加到您的项目中。Quasar CLI 提供router
属性,如果您有其他全局属性,则可能需要添加更多属性。调整状态接口以适应您的应用程序。
import { InjectionKey } from 'vue'
import { Router } from 'vue-router'
import {
createStore,
Store as VuexStore,
useStore as vuexUseStore,
} from 'vuex'
export interface StateInterface {
// Define your own store structure, using submodules if needed
// example: ExampleStateInterface;
// Declared as unknown to avoid linting issue. Best to strongly type as per the line above.
example: unknown
}
// provide typings for `this.$store`
declare module 'vue' {
interface ComponentCustomProperties {
$store: VuexStore<StateInterface>
}
}
// Provide typings for `this.$router` inside Vuex stores
declare module "vuex" {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface Store<S> {
readonly $router: Router;
}
}
// provide typings for `useStore` helper
export const storeKey: InjectionKey<VuexStore<StateInterface>> = Symbol('vuex-key')
export function useStore() {
return vuexUseStore(storeKey)
}
// createStore<StateInterface>({ ... })
PWA 模式
如果您正在使用PWA 模式,请对您的项目进行以下修改,并创建任何不存在的文件
/* eslint-disable */
declare namespace NodeJS {
interface ProcessEnv {
SERVICE_WORKER_FILE: string;
PWA_FALLBACK_HTML: string;
PWA_SERVICE_WORKER_REGEX: string;
}
}
// at the top of the file
declare const self: ServiceWorkerGlobalScope &
typeof globalThis & { skipWaiting: () => void };
{
"extends": "../tsconfig.json",
"compilerOptions": {
"lib": ["WebWorker", "ESNext"]
},
"include": ["*.ts", "*.d.ts"]
}
const { resolve } = require('node:path');
module.exports = {
parserOptions: {
project: resolve(__dirname, './tsconfig.json'),
},
overrides: [
{
files: ['custom-service-worker.ts'],
env: {
serviceworker: true,
},
},
],
};
Electron 模式
如果您正在使用Electron 模式,请将以下部分添加到您的项目中。
/* eslint-disable */
declare namespace NodeJS {
interface ProcessEnv {
QUASAR_PUBLIC_FOLDER: string;
QUASAR_ELECTRON_PRELOAD_FOLDER: string;
QUASAR_ELECTRON_PRELOAD_EXTENSION: string;
APP_URL: string;
}
}
BEX 模式
如果您正在使用BEX 模式,请将以下部分添加到您的项目中。根据您正在使用的事件,您可能需要调整它以满足您的需求。键是事件名称,值是一个元组,其中第一个元素是输入,第二个元素是输出类型。
declare module '@quasar/app-vite' {
interface BexEventMap {
/* eslint-disable @typescript-eslint/no-explicit-any */
log: [{ message: string; data?: any[] }, never];
getTime: [never, number];
'storage.get': [{ key: string | null }, any];
'storage.set': [{ key: string; value: any }, any];
'storage.remove': [{ key: string }, any];
/* eslint-enable @typescript-eslint/no-explicit-any */
}
}