uni-app 微信小程序开发:TypeScript 常用语法总结

📅 2026/7/11 23:08:52 👁️ 阅读次数 📝 编程学习
uni-app 微信小程序开发:TypeScript 常用语法总结

目录

1. 基础类型声明

2. 接口与类型别名

3. 联合类型与字面量类型

4. 泛型 - 封装网络请求

5. 枚举

6. Vue 组件 Props 的类型定义

7. Composition API 与 Ref 的类型

9. 高级工具类型(Pick / 交叉类型)- 复杂表单参数的组装

8. 类型断言 - 初始化空对象与类型转换

9. uni-app/微信小程序原生 API 的类型

在 uni-app 微信小程序项目开发中,使用 TypeScript (TS) 相比传统的 JavaScript (JS) 最大的优势在于静态类型检查代码提示更完善以及在开发阶段捕获潜在错误

1. 基础类型声明

TS 最基础的功能是给变量、函数参数和返回值添加类型约束。

JS 写法:

let count = 0; function add(a, b) { return a + b; }

TS 写法:

let count: number = 0; // 约束参数和返回值类型,防止传入字符串导致意外行为 function add(a: number, b: number): number { return a + b; }

2. 接口与类型别名

在处理小程序后端返回的数据或复杂对象时,定义结构至关重要。

JS 写法:

// JS 只能靠注释说明,没有约束 function getUser() { return { id: 1, name: '张三', age: 18 }; } let user = getUser(); console.log(user.nme); // 拼写错误,JS运行时才报错或静默失败

TS 写法:

// 定义接口 interface User { id: number; name: string; age?: number; // 可选属性(带问号) readonly createTime: string; // 只读属性 } function getUser(): User { return { id: 1, name: '张三', createTime: '2023-01-01' }; } let user = getUser(); console.log(user.nme); // 编译报错:Property 'nme' does not exist on type 'User'

3. 联合类型与字面量类型

小程序中常有状态值(如订单状态:1待付款,2已付款)或固定类型的参数。

JS 写法:

let status = 1; // 可能被误赋值为 '1' 或其他无关数字 function setTheme(theme) {} // theme是什么完全不知道

TS 写法:

// 联合类型 let status: number | string = 1; status = 'success'; // 允许 // 字面量联合类型(常用于状态机、枚举替代) type OrderStatus = 'unpaid' | 'paid' | 'shipped' | 'completed'; function setOrderStatus(status: OrderStatus) { // ... } setOrderStatus('paid'); // 正确 setOrderStatus('cancel'); // 编译报错

4. 泛型 - 封装网络请求

封装uni.request时,泛型是 TS 最强大的功能之一,能让你在不同的接口调用中获得不同的数据类型提示。

JS 写法:

// 封装 function request(url, data) { return new Promise((resolve, reject) => { uni.request({ url, data, success: res => resolve(res.data), fail: err => reject(err) }); }); } // 调用 const res = await request('/api/user', {}); console.log(res.name); // 没有提示,不知道res里有什么

TS 写法:

// 封装:使用泛型 T 表示返回的数据结构 function request<T = any>(url: string, data?: any): Promise<T> { return new Promise((resolve, reject) => { uni.request({ url, data, success: (res) => resolve(res.data as T), fail: (err) => reject(err) }); }); } // 定义接口数据类型 interface UserInfo { id: number; name: string; } // 调用:传入具体类型,res 自动推导为 UserInfo const res = await request<UserInfo>('/api/user', {}); console.log(res.name); // 有完美代码提示!

5. 枚举

用于管理项目中全局的常量(如 tabBar 的 pagePath、错误码等)。

JS 写法:

const Color = { RED: 'red', GREEN: 'green' }; console.log(Color.RED);

TS 写法:

enum Color { RED = 'red', GREEN = 'green', BLUE = 'blue' } console.log(Color.RED); // 代码提示更好,且防止使用未定义的枚举值

6. Vue 组件 Props 的类型定义

在 uni-app 中,Vue 3 的组件 Props 定义是高频场景。

JS 写法:

export default { props: { title: String, user: Object // 不知道user里面有什么字段 } }

TS 写法:

import { defineComponent, PropType } from 'vue'; interface UserProps { id: number; name: string; } export default defineComponent({ props: { title: { type: String, required: true }, // 使用 PropType 断言对象类型 user: { type: Object as PropType<UserProps>, required: true }, // 验证数组类型 list: { type: Array as PropType<string[]>, default: () => [] } }, setup(props) { console.log(props.user.name); // 完美提示 } })

7. Composition API 与 Ref 的类型

在 uni-app 的 Vue3 开发中,refreactive的类型定义。

JS 写法:

import { ref, reactive } from 'vue'; const count = ref(0); // 自动推断为数字 const user = ref(null); // 推断为 null,后续赋值对象无提示

TS 写法:

import { ref, reactive } from 'vue'; interface UserInfo { name: string; age: number; } // 1. ref 的泛型用法 const user = ref<UserInfo | null>(null); user.value = { name: '张三', age: 18 }; // 正确 user.value.age = 20; // 提示正常 // 2. reactive 直接有类型推导 const state = reactive({ list: [] as string[] // 在对象内部断言 });

9. 高级工具类型(Pick / 交叉类型)- 复杂表单参数的组装

在 uni-app 小程序开发中,经常遇到“编辑个人资料”表单。我们需要从完整的用户详情ProfileDetail中提取部分字段,再合并一些特有的省市编码字段用于提交给后端。此时Pick&(交叉类型)能大显身手。

Pick:它是 TypeScript 的内置工具类型。它的作用就像“挑水果”一样,从一个已有的类型中,精准挑选出你指定的几个属性,丢弃其他属性,从而生成一个新的子类型。

JS 写法:

// JS 无法复用已有对象结构,只能手写全部字段,极易遗漏或写错 /** * @typedef {Object} ProfileParams * @property {string} nickname - 昵称 * @property {string} gender - 性别 * @property {string} provinceCode - 省份编码 (可选) * ... */ function updateProfile(params) { console.log(params.nickname); }

TS 写法:

// 假设这是从后端获取的用户详情结构 interface ProfileDetail { id: string; nickname: string; gender: string; birthday: string; profession: string; // ... 其他几十个字段 } // 1. 使用 Pick 挑出需要编辑的字段,使用 & 补充提交时需要的额外字段 export type ProfileParams = Pick< ProfileDetail, 'nickname' | 'gender' | 'birthday' | 'profession' > & { /** 省份编码 */ provinceCode?: string /** 城市编码 */ cityCode?: string /** 区县编码 */ countyCode?: string } // 2. 提交函数约束 function updateProfile(params: ProfileParams) { console.log(params.nickname); // 完美提示 // console.log(params.id); // 编译报错!防止误传 id 给后端 } // 调用时严格校验字段 updateProfile({ nickname: '张三', gender: '男', birthday: '2000-01-01', profession: '码农', // cityCode: '110100' // 可选字段不传也不报错 });

优势:如果后端修改了ProfileDetail中的birthday字段名为birthDate,你的ProfileParams会立刻在编译阶段红线报错,彻底杜绝前后端字段对不上的隐患。

8. 类型断言 - 初始化空对象与类型转换

在页面初始渲染时,我们常定义一个空对象用来存放稍后从后端请求回来的数据。但在 TS 中,如果直接给ref赋空对象{},会报错提示缺少必填属性。此时使用as关键字进行类型断言,相当于告诉编译器:“我知道它是空对象,但你先按这个类型给我提示”。

JS 写法:

import { ref } from 'vue'; // JS 毫无提示,后续给 profile 赋值时打错字也不会报错 const profile = ref({});

TS 写法:

import { ref } from 'vue'; // 1. 定义详情接口 interface ProfileDetail { id: number; nickname: string; gender: string; } // 2. 使用 as 进行类型断言,初始化为空对象但拥有完整类型提示 const profile = ref<ProfileDetail>({} as ProfileDetail); // 3. 模板中使用 profile.nickname 会有代码提示 // 4. 异步获取数据后赋值 profile.value = { id: 1, nickname: '张三', gender: '男' }; // 注意:断言是双刃剑。如果用 as 强行断言错误类型,会骗过编译器: // let a = 'hello' as number; // 报错,TS不允许差异过大的断言 // let b = ({} as any) as number; // 滥用 any 断言会导致运行时错误,需谨慎

优势:完美解决了“声明时还没数据,用空对象初始化会报错”的尴尬,同时保证了后续业务代码拥有完美的类型推导和防错能力。

9. uni-app/微信小程序原生 API 的类型

uni-app 官方提供了完整的 d.ts 文件,所有的uni.xxxAPI 都有类型支持。

JS 写法:

uni.getSystemInfo({ success: function(res) { console.log(res.model); // 靠记忆或查文档才知道有model console.log(res.windowWidth); // 拼错完全没提示 } });

TS 写法:

uni.getSystemInfo({ success: (res) => { // res 自动推断为 UniApp.GetSystemInfoResult console.log(res.model); // 有提示 console.log(res.windowWidth); // 有提示 // console.log(res.windowHight); // 拼错会有红线报错 } });