第十二章:TypeScript 深度集成

第十二章:TypeScript 深度集成

12.1 Vite + TypeScript 基础

开箱即用

Vite 原生支持 TypeScript,无需额外配置:

bash 复制代码
npm create vite@latest my-app -- --template vue-ts
# 或 react-ts

工作原理

  • 使用 esbuild 编译 TypeScript
  • 仅转换,不进行类型检查
  • 开发环境极速,构建时可通过插件检查

12.2 tsconfig.json 最佳配置

基础配置

json 复制代码
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "jsx": "preserve",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "allowImportingTsExtensions": true,
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"],
  "exclude": ["node_modules", "dist"]
}

路径映射

json 复制代码
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@components/*": ["./src/components/*"],
      "@utils/*": ["./src/utils/*"]
    }
  }
}

同时需要在 Vite 中配置:

javascript 复制代码
resolve: {
  alias: {
    '@': '/src',
    '@components': '/src/components',
    '@utils': '/src/utils'
  }
}

12.3 类型声明文件

环境变量类型

typescript 复制代码
// src/vite-env.d.ts
/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_API_URL: string
  readonly VITE_APP_TITLE: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

模块类型声明

typescript 复制代码
// src/shims-vue.d.ts
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

// 声明图片模块
declare module '*.svg' {
  const src: string
  export default src
}

// 声明 CSS 模块
declare module '*.module.css' {
  const classes: { [key: string]: string }
  export default classes
}

12.4 组件类型推导

Vue 组件类型

vue 复制代码
<script setup lang="ts">
// 定义 Props 类型
interface Props {
  title: string
  count?: number
  items: string[]
}

const props = withDefaults(defineProps<Props>(), {
  count: 0
})

// 定义 Emits 类型
const emit = defineEmits<{
  (e: 'update', value: string): void
  (e: 'delete', id: number): void
}>()

// 定义 Slots 类型
defineSlots<{
  default(props: { item: string }): any
  header(): any
}>()
</script>

React 组件类型

tsx 复制代码
import { FC } from 'react'

interface ButtonProps {
  onClick?: () => void
  children: React.ReactNode
  variant?: 'primary' | 'secondary'
}

const Button: FC<ButtonProps> = ({ onClick, children, variant = 'primary' }) => {
  return (
    <button onClick={onClick} className={`btn btn-${variant}`}>
      {children}
    </button>
  )
}

12.5 类型检查工具

使用 vite-plugin-checker

bash 复制代码
npm install -D vite-plugin-checker
javascript 复制代码
import checker from 'vite-plugin-checker'

export default defineConfig({
  plugins: [
    checker({
      typescript: true,
      vueTsc: true,
      eslint: {
        lintCommand: 'eslint "./src/**/*.{ts,tsx,vue}"'
      }
    })
  ]
})

单独运行类型检查

json 复制代码
{
  "scripts": {
    "type-check": "tsc --noEmit",
    "build": "npm run type-check && vite build"
  }
}

12.6 高级类型技巧

动态导入类型

typescript 复制代码
// 获取导入模块的类型
const MyComponent = () => import('./MyComponent.vue')
type MyComponentType = Awaited<typeof MyComponent>

// 泛型组件
function useList<T extends { id: number }>(items: T[]) {
  const findById = (id: number): T | undefined => {
    return items.find(item => item.id === id)
  }
  return { findById }
}

工具类型使用

typescript 复制代码
// Partial、Required、Pick 等
interface User {
  id: number
  name: string
  email: string
  age?: number
}

type UserUpdate = Partial<User>
type UserBasic = Pick<User, 'id' | 'name'>

// 条件类型
type IsArray<T> = T extends any[] ? true : false
type A = IsArray<string[]> // true
type B = IsArray<string>   // false

12.7 构建类型产物

库模式类型声明

javascript 复制代码
// vite.config.js
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'

export default defineConfig({
  plugins: [
    dts({
      insertTypesEntry: true,
      rollupTypes: true
    })
  ],
  build: {
    lib: {
      entry: 'src/index.ts',
      formats: ['es', 'cjs']
    }
  }
})

package.json 配置

json 复制代码
{
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs",
      "types": "./dist/index.d.ts"
    }
  }
}

12.8 常见类型问题

问题 1:找不到模块

typescript 复制代码
// 添加类型声明
declare module 'my-module' {
  export function doSomething(): void
}

问题 2:全局类型扩展

typescript 复制代码
// global.d.ts
export {}

declare global {
  interface Window {
    myGlobalVar: string
  }
}

问题 3:第三方库类型缺失

bash 复制代码
# 安装 @types 包
npm install -D @types/lodash

# 或创建自定义声明
declare module 'untyped-lib'

本章小结

TypeScript + Vite 提供了完美的类型安全开发体验:

  • 零配置开箱即用
  • 完善的类型声明支持
  • 路径映射和组件类型推导
  • 构建时类型检查
  • 库模式类型产物生成
相关推荐
JustHappy4 小时前
古法编程秘籍(六):程序到底是怎么跑起来的?从 IO 到中断,一次讲明白
前端·后端·全栈
HYCS5 小时前
用pixi.js实现fabric.js(六):从线性代数的角度理解编辑器交互
前端·javascript·canvas
卷帘依旧5 小时前
useImperativeHandle的作用
前端
卷帘依旧5 小时前
Hooks在Fiber上的存储原理
前端
you45805 小时前
学成在线--day02 CMS前端开发(含Vue基础知识得回顾)
前端·javascript·vue.js
xiaofeichaichai5 小时前
虚拟 DOM
前端·javascript·vue.js
2401_878454535 小时前
前端高频得手写题
前端
初一初十6 小时前
vue3实现的纯前端护肤品商城网站
前端·javascript·vue.js·前端框架
卷帘依旧6 小时前
React状态管理方案怎么选
前端