刚开始用TypeScript的时候,我最大的感觉就是代码变啰嗦了。
以前JavaScript一行能搞定的事情,换成TypeScript之后要多写不少东西,什么interface、type、泛型,看着就头大(懒)。
但后来参与了一些稍微大点的项目,我才慢慢意识到,TypeScript真正的好处不是"让代码看起来更专业",而是能在你写代码的时候就帮你发现问题(帮助他人emm)。
类型定义得贴着业务来
比如一个用户对象:
interface User {
id: number
name: string
email: string
}然后:
function getUserName(user: User) {
return user.name
}这个很好理解,就是拿某个用户的name。
但到了实际项目里,类型定义最好能直接反映业务模型,而不是随便写几个字段糊弄过去。
比如接口返回的结构:
interface UserListResponse {
items: User[]
total: number
page: number
pageSize: number
}那请求函数就可以直接这样写:
async function getUsers(): Promise<UserListResponse> {
// ...
}调用的人一眼就能看出返回了什么,不用再去翻文档或者看网络请求。
别到处用any
初学ts时,any这玩意儿,用一次就停不下来,遇事不决直接any。
遇到类型报错,随手一写:
const data: any = response.data问题立马消失,心情舒畅,但实际上只是把问题往后推了。
假如这个数据本来应该是:
interface User {
id: number
name: string
}你却写成了:
const user: any = response.data那后面这些写法TypeScript都不会报错:
user.id.toUpperCase()
user.username
user.xxx等到运行时报错,再去查是哪里的问题,反而更费时间。项目越大,any埋的坑就越多。
unknown比any更适合处理不确定的数据
如果确实遇到一个变量类型没法提前确定,可以用unknown:
const data: unknown = response.data然后在使用之前先做判断:
if (typeof data === 'string') {
console.log(data.toUpperCase())
}或者:
if (Array.isArray(data)) {
console.log(data.length)
}unknown和any的区别在于:
unknown接受未知数据,但不会默认你什么都能做,想用必须先判断。
在处理第三方API、后端返回的JSON、或者用户输入的时候,这个习惯特别有用。
type和interface怎么选
比如:
type UserId = string
interface User {
id: UserId
name: string
}对于对象结构,我一般习惯用interface。
而像联合类型、工具类型这种,用type更顺手:
type Status = 'pending' | 'success' | 'error'没必要为了所谓的"统一风格"硬用一种,哪个合适就用哪个。
泛型解决的是实际问题
泛型最常见的场景就是封装通用逻辑。比如统一的API响应结构:
interface ApiResponse<T> {
code: number
message: string
data: T
}然后定义用户相关的类型:
interface User {
id: number
name: string
}那么:
type UserResponse = ApiResponse<User>列表也一样:
type UserListResponse = ApiResponse<User[]>这样一个ApiResponse就能覆盖所有接口,不用每个都重新写一遍。
TypeScript别搞成负担
我现在越来越觉得:
类型系统是帮我们省时间的,不是用来折腾人的。
如果为了一个很简单的对象,硬写了几十行复杂类型,最后维护成本比写JavaScript还高,那就走偏了。
在实际项目里,我比较看重这几件事:
- API的请求和返回结构要清晰
- 核心业务模型有类型覆盖
- 公共函数的参数和返回值明确
- 尽量不用any
- 复杂逻辑适当用泛型
- 类型定义贴近实际业务
TypeScript的目标不是让每一行代码都带着类型,而是让关键的地方有足够的信息。
这也是我从"会用TypeScript"到"真正离不开TypeScript"之后,最大的感受变化。