# TypeScript 引入记录
## 1. 引入原因
### 1.1 为什么引入 TypeScript
| 原因 | 说明 |
|------|------|
| **类型安全** | 在编码阶段发现类型错误,减少运行时 bug |
| **IDE 智能提示** | 输入 `user.` 自动提示属性,提升开发效率 |
| **代码可读性** | 类型定义即文档,代码意图更清晰 |
| **重构安全** | 修改接口定义后,所有使用处自动报错 |
| **长期维护** | 项目持续迭代,类型系统有助于后期维护 |
---
## 2. 安装 TypeScript
### 2.1 执行命令
npm install -D typescript @types/node
### 2.2 说明
| 包 | 作用 |
|---|------|
| `typescript` | TypeScript 编译器 |
| `@types/node` | Node.js 类型定义 |
---
## 3. 创建 TypeScript 配置文件
### 3.1 文件路径
`tsconfig.json`(项目根目录)
### 3.2 完整代码
```json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": false,
"jsx": "preserve",
"resolveJsonModule": true,
"esModuleInterop": true,
"skipLibCheck": true,
"allowJs": true,
"checkJs": false,
"types": ["vite/client", "element-plus/global"]
},
"include": ["resources/js/**/*.ts", "resources/js/**/*.d.ts", "resources/js/**/*.vue"],
"exclude": ["node_modules", "public"]
}
```
### 3.3 配置说明
| 配置项 | 作用 |
|--------|------|
| `"strict": false` | 降低严格程度,减少报错,后续可逐步开启 |
| `"allowJs": true` | 允许混合使用 `.js` 和 `.ts` 文件 |
| `"checkJs": false` | 不检查 `.js` 文件 |
| `"jsx": "preserve"` | 保留 JSX 语法,由 Vite 处理 |
| `"types": [...]` | 引入 Vite 和 Element Plus 类型定义 |
---
## 4. 添加类型声明文件
### 4.1 文件路径
`resources/js/admin/vite-env.d.ts`
### 4.2 完整代码
```typescript
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any>;
export default component;
}
```
### 4.3 说明
| 代码 | 作用 |
|------|------|
| `/// <reference types="vite/client" />` | 引入 Vite 客户端类型 |
| `declare module '*.vue'` | 声明 `.vue` 文件的模块类型 |
---
## 5. 修改 Vite 配置
### 5.1 文件路径
`vite.config.js`
### 5.2 完整代码
```javascript
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel({
input: [
'resources/css/app.css',
'resources/js/app.js',
'resources/js/admin/main.ts', // 改为 .ts
],
refresh: true,
}),
vue({
script: {
defineModel: true,
propsDestructure: true,
},
}),
],
});
```
### 5.3 说明
将后台入口文件从 `main.js` 改为 `main.ts`,Vite 会自动识别 TypeScript。
---
## 6. 重命名入口文件
### 6.1 执行命令
mv resources/js/admin/main.js resources/js/admin/main.ts
### 6.2 修改 main.ts 内容
**文件路径**:`resources/js/admin/main.ts`
```typescript
import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component);
}
app.use(ElementPlus);
app.use(router);
app.mount('#app');
```
---
## 7. 修改 Login.vue 支持 TypeScript
### 7.1 文件路径
`resources/js/admin/views/Login.vue`
### 7.2 关键修改
将 `<script setup>` 改为 `<script setup>`,并添加类型定义。
### 7.3 完整代码
<script setup>
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import { User, Lock } from '@element-plus/icons-vue';
// 定义表单数据类型
interface LoginForm {
email: string;
password: string;
}
const formRef = ref();
const loading = ref<boolean>(false);
const form = reactive<LoginForm>({
email: '',
password: '',
});
const rules = {
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ type: 'email' as const, message: '邮箱格式不正确', trigger: 'blur' },
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, message: '密码至少6位', trigger: 'blur' },
],
};
const handleLogin = () => {
if (!formRef.value) return;
formRef.value.validate(async (valid: boolean) => {
if (!valid) return;
loading.value = true;
setTimeout(() => {
loading.value = false;
ElMessage.warning('后端API开发中,暂不支持登录');
}, 500);
});
};
</script>
### 7.4 代码说明
| 代码 | 作用 |
|------|------|
| `interface LoginForm` | 定义表单数据类型 |
| `loading.value = ref<boolean>(false)` | 声明 loading 为布尔类型 |
| `form = reactive<LoginForm>({...})` | 声明 form 符合 LoginForm 接口 |
| `valid: boolean` | 声明验证回调参数类型 |
| `as const` | 将字符串字面量类型收窄为具体值 |
---
## 8. 修改后台视图
### 8.1 文件路径
`resources/views/admin.blade.php`
### 8.2 修改
将:
@vite('resources/js/admin/main.js')
改为:
@vite('resources/js/admin/main.ts')
---
## 9. 编译验证
### 9.1 执行命令
```bash
npm run build
```
### 9.2 预期结果
编译成功,无报错,生成 `public/build/assets/` 目录。
## 10. TypeScript 带来的好处(示例对比)
### 10.1 JavaScript 写法(之前)
const form = reactive({
email: '',
password: '',
});
// 写错属性名不会报错
console.log(form.emial); // undefined
### 10.2 TypeScript 写法(之后)
interface LoginForm {
email: string;
password: string;
}
const form = reactive<LoginForm>({
email: '',
password: '',
});
// 写错属性名会报错
console.log(form.emial); // ❌ 类型“LoginForm”上不存在属性“emial”