为什么捐赠
API 浏览器
联系站长
Quasar CLI with Vite - @quasar/app-vite
TypeScript 支持

如果你在创建项目时没有选择 TypeScript 支持,后续仍然可以添加。本指南将告诉你如何为已有的基于 JavaScript 的 Quasar 项目添加 TypeScript 支持。

TIP

如果你在创建项目时已经选择了 TypeScript 支持,可以跳过本指南。

安装 TypeScript 支持

安装 typescript 包:


$ yarn add --dev typescript@~5.5.3

然后在项目根目录创建 /tsconfig.json 文件,内容如下:

/tsconfig.json

{
  "extends": "./.quasar/tsconfig.json"
}

在项目根目录运行 $ quasar prepare

现在你就可以在项目中使用 TypeScript 了。注意某些 IDE 可能需要重启才能完全识别新的配置。

TIP

请记住,你必须将 JavaScript 文件的扩展名改为 .ts 才能在其中编写 TypeScript 代码。要在 Vue 文件中使用 TypeScript,需要在 script 标签上添加 lang="ts" 属性,如 <script lang="ts"><script setup lang="ts">

WARNING

如果忘记添加 tsconfig.json 文件,应用在编译时会报错!

Lint 配置

你可能需要查看相关的配置要求,详见这里

TypeScript 声明文件

如果你在项目脚手架搭建时选择了 TypeScript 支持,以下声明文件会自动生成。如果创建项目时没有启用 TypeScript 支持,请手动创建:

/src/env.d.ts

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 会在 .quasar/pinia.d.ts 中自动扩展 router 属性。因此,不要在 src/stores/index.ts 文件中手动向 PiniaCustomProperties 接口添加 router 属性。

/src/stores/index.ts

import { defineStore } from '#q-app/wrappers'
import { createPinia } from 'pinia'
- import { type Router } from 'vue-router';

/*
 * When adding new properties to stores, you should also
 * extend the `PiniaCustomProperties` interface.
 * @see https://pinia.vuejs.org/core-concepts/plugins.html#Typing-new-store-properties
 */
declare module 'pinia' {
  export interface PiniaCustomProperties {
-    readonly router: Router;
+    // add your custom properties here, if any
  }
}

PWA 模式

如果你使用了 PWA 模式,请对项目做以下修改,如果文件不存在则创建它们:

/src-pwa/pwa-env.d.ts

declare namespace NodeJS {
  interface ProcessEnv {
    SERVICE_WORKER_FILE: string;
    PWA_FALLBACK_HTML: string;
    PWA_SERVICE_WORKER_REGEX: string;
  }
}
/src-pwa/custom-service-worker.ts

// at the top of the file
declare const self: ServiceWorkerGlobalScope & typeof globalThis & { skipWaiting: () => void };
/src-pwa/tsconfig.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "lib": ["WebWorker", "ESNext"]
  },
  "include": ["*.ts", "*.d.ts"]
}

Electron 模式

如果你使用了 Electron 模式,请在项目中添加以下内容。

/src-electron/electron-env.d.ts

declare namespace NodeJS {
  interface ProcessEnv {
    QUASAR_PUBLIC_FOLDER: string;
    QUASAR_ELECTRON_PRELOAD_FOLDER: string;
    QUASAR_ELECTRON_PRELOAD_EXTENSION: string;
    APP_URL: string;
  }
}

BEX 模式

如果你使用了 BEX 模式,请在项目中添加以下内容。你可能需要根据实际使用的事件来调整它。其中键(key)是事件名称,值(value)是一个元组,第一个元素是输入类型,第二个元素是输出类型。

/src-bex/background.ts

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 */
  }
}

你还需要在每个内容脚本文件中添加:

/src-bex/my-content-script.ts

declare module "@quasar/app-vite" {
  interface BexEventMap {
    /* eslint-disable @typescript-eslint/no-explicit-any */
    "some.event": [{ someProp: string }, void];
    /* eslint-enable @typescript-eslint/no-explicit-any */
  }
}

配置 TypeScript

tsconfig.json

注意项目根目录下的 /tsconfig.json 文件。Quasar CLI 通过该文件来判断你是否需要 TypeScript 支持。其内容应如下所示:

/tsconfig.json

{
  "extends": "./.quasar/tsconfig.json"
}

以下是生成的 tsconfig(非严格模式)示例,供参考。你的 /tsconfig.json 正是继承自它:

/.quasar/tsconfig.json

{
  "compilerOptions": {
    "esModuleInterop": true,
    "skipLibCheck": true,
    "target": "esnext",
    "allowJs": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true,
    "module": "preserve",
    "noEmit": true,
    "lib": [
      "esnext",
      "dom",
      "dom.iterable"
    ],
    "paths": { ... }
  },
  "exclude": [ ... ]
}

要正确运行类型检查和代码检查,需要 .quasar/tsconfig.json 文件存在。该文件在运行 quasar devquasar build 命令时会自动生成。不过作为轻量替代方案,你也可以使用 CLI 命令 quasar prepare 来生成 .quasar/tsconfig.json 文件和一些类型文件。这在 CI/CD 流水线中特别有用。

$ quasar prepare

你可以将它添加为 postinstall 脚本,确保在安装依赖后自动运行。这对于首次拉取项目的开发者尤其有帮助。

/package.json

{
  "scripts": {
    "postinstall": "quasar prepare"
  }
}

得益于这一机制,Capacitor 依赖会正确关联到项目的 TypeScript 配置中。这意味着你不需要重复安装依赖 – 一次在 /src-capacitor 中,一次在根目录中。

另一个好处是文件夹别名(quasar.config file > build > alias)会被 TypeScript 自动识别。因此你可以移除 tsconfig.json > compilerOptions > paths 的配置。如果你在使用 vite-tsconfig-paths 之类的插件,可以卸载它,直接以 quasar.config file > build > alias 作为唯一的路径配置来源。

如果你使用了 ESLint,建议在 ESLint 配置中启用 @typescript-eslint/consistent-type-imports 规则。如果你还没有配置代码检查,可以在 tsconfig.json 中使用 verbatimModuleSyntax 作为替代方案(不同于 ESLint 规则,它无法自动修复)。这些配置有助于统一常规导入和纯类型导入的写法。更多信息请参阅 typescript-eslint 博客 - Consistent Type Imports and Exports: Why and How。以下是一个示例:

/eslint.config.js

rules: {
  // ...
  '@typescript-eslint/consistent-type-imports': [
    'error',
    { prefer: 'type-imports' },
  ],
  // ...
}

quasar.config.ts

你可以通过 quasar.config file > build > typescript 来控制 TypeScript 相关的行为。在配置中添加以下内容:

/quasar.config.ts

build: {
+  typescript: {
+    strict: true, // (recommended) enables strict settings for TypeScript
+    vueShim: true, // required when using ESLint with type-checked rules, will generate a shim file for `*.vue` files
+    extendTsConfig (tsConfig) {
+      // You can use this hook to extend tsConfig dynamically
+      // For basic use cases, you can still update the usual tsconfig.json file to override some settings
+    },
+  }
}

如果需要,你应该可以直接将 strict 选项设置为 true 而不会遇到太多问题。但如果确实出现了问题,你可以在 tsconfig.json 文件中将"有问题"的选项设置为 false,至少先这样用着,直到你有时间去修复它们。

如果你在使用 ESLint 的类型检查规则,请启用 vueShim 选项以保持之前 shim 文件的行为。如果你的项目在没有该选项的情况下运行正常,则不需要启用它。

/quasar.config.ts

build: {
  typescript: {
+    vueShim: true // required when using ESLint with type-checked rules, will generate a shim file for `*.vue` files
  }
}