節省型別管理成本的最佳實踐

範例專案位置:

https://github.com/fortes1219/vue3_typescript

一、專案基礎架構

<aside> 💡

一個完整的專案必定需要分工明確且依賴樹清晰的架構設計。 我們以 Feature Based 架構作為本次課程的核心概念設計,並且使用 ts-rest 與 Zod 兩個套件簡化在 API 請求上的型別與 interface 管理。

</aside>

src/
├── assets/           # 靜態資源
│   └── images/
├── styles/           # 樣式表
│   └── xxx.scss
├── components/       # 全域共用元件舉例
│   ├── table/
│   │   ├── DataTable.vue
│   │   └── TableFilter.vue
│   ├── form/
│   │   ├── SearchForm.vue
│   │   └── FilterForm.vue
│   └── common/
│       ├── ConfirmDialog.vue
│       └── StatusBadge.vue
│
├── composables/      # 可複用邏輯
│   ├── auth/
│   │   ├── usePermission.ts
│   │   └── useRole.ts
│   └── ui/
│       ├── useModal.ts
│       └── useToast.ts
│
├── constants/       # 常數定義
│   ├── enums.ts
│   └── permission.ts
│
├── middleware/      # 中間件
│   ├── auth.ts
│   └── error.ts
│
├── plugins/         # 插件
│   └── i18n/        # 多語目錄
│       └── index.ts # 入口檔
│
├── services/        # API 服務
│   ├── api/         # api 個別實體
│   │   ├── index.ts # 調用各組API實際位置
│   │   └── xxx.ts
│   ├── contract/    # ts-rest api contract 個別實體
│   │   ├── index.ts
│   │   └── xxx.ts
│   ├── schema/      # Zod 驗證 schema 結構
│   │   ├── index.ts
│   │   └── xxx.ts
│   └── request.ts   # Axios 實例     
│
├── stores/          # 狀態管理
│   ├── permission.ts
│   └── user.ts
│
├── types/          # TypeScript 類型
│   ├── api.d.ts
│   ├── components.d.ts
│   └── global.d.ts
│
├── utils/          # 工具函數
│   ├── format.ts
│   ├── validator.ts
│   └── helper.ts
│
├── views/          # 頁面
│   ├── goods/      # 商品管理
│   │   ├── composables/     # 商品管理邏輯
│   │   │   ├── useGoodsList.ts
│   │   │   └── useGoodsOrders.ts
│   │   ├── components/      # 商品頁面專用元件
│   │   │   └── OrderTable.vue
│   │   ├── GoodsList.vue
│   │   └── OrderRecords.vue
│   │
│   └── users/     # 會員管理
│       ├── composables/
│       │   └── useUserList.ts
│       ├── components/
│       │   └── UserForm.vue
│       └── UserList.vue 
│
├── App.vue
├── main.ts
└── Login.vue

二、替 API 配置 Schema/Contract

[課堂後補內容,先乖乖聽講]

首先我們替Services下配置兩個目錄,分別是 schemacontract

並且在schema下開個index.tsauth.tscontract也一樣。

services/schema/index.ts

// 統一導出,這樣到時候只需要 import { xxx } from '@/services/schema'
export * from './login';
// 以及你其他的 schema 來源