这段时间运用typescript有了更深入的了解,在此之前,一直使用的javascript开发项目,最近在做的一个项目恰巧用到了,然后就开启了边学边做的历程,经过这段时间的摸索,也总结一些技巧,以下总结的几点:
1. satisfies
用于更好的类型推断
该运算符验证表达式是否与类型匹配,同时保留字面量类型,这对于需要兼顾类型安全性和精确推断的配置对象尤为重要。
ts
// 不使用
const Config1: Record<string, string | number> = {
port: 3000,
host: 'localhost'
}
// 使用
const Config2 = {
port: 3000,
host: 'localhost'
} satisfies Record<string, string | number>
2. 不可变类型的Const断言
添加as const
到对象后,Typescript会将所有属性变为只读属性,并推断出具体的类型,这对于不可更改配置对象尤为重要
ts
const User = {
name: 'zhansan'
age: 18,
sex: 'man'
} as Const
3. 模板字符串字面量类型
模板字面量类型允许你创建与特定字符串匹配的类型,适合用于API端点,事件名称和任何结构化字符串
ts
type EventName = `on${Capitalize<string>}`
// 正确示范:'onChange' 'onHandle' onClick'
// 错误示范:'change' 'handle' 'click'
type Method = 'GET' | 'POST' | 'DELETE' | 'PUT'
type Endpoint = `/api/${string}`
type Route = `${Method} ${Endpoint}`
// 正确示范:GET /api/users
// 错误示范:GET /users
function MakeRoute(route: Route): void {
return route
}
MakeRoute('GET /api/users')
4. 自定义类型的关键字定义
在创建函数时指定对象类型
ts
function isString(value: unKnown) value is string {
return typeof value === 'string'
}
5. 使用索引访问类型
使用索引访问类型
使用括号表示法访问类型定义,这可以保持类型的DRY原则,并在源类型发生变化保持更新。
ts
type User = {name: string, age: number}
type UserName = User['name'] // string
6. 三元运算符动态判断对象类型
使用条件判断对象类型,常见的使用三元运算符判断
ts
type isArray<T> = T extends any[] ? true : false
// 提取数据元素类型
type Flatten<T> = T extends Array[infer U] ? U : T
type Flatten1 = Flatten<string[]> // string
type Flatten2 = Flatten<number> // number
// 其他案列
type ApiResponse<T> = T extends {error: string} ? {success: false, error: string : {success: true, data: T}
7. 函数重载,可以更好的得到编辑器的提示
php
使用函数重载,获得更好的提示与准确的类型保护
```ts
function getUserById(id: string): User {}
// override
function getUserById(id: string): User {
// 写逻辑判断
const user = {}
return user
}
```
8. keyof类型约束
可以使用keyof限制传递类型,可以更好避免类型推断错误
ts
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key]
}
9. 模块扩充
根据需要扩展现有模块类型,通常是向窗口添加属性或者第三方库
ts
declare global {
interface Window {
analytics: AnalyticsClient
}
}
10. 类型导入
ts
import type { User } from './types'
11. 断言函数
创建断言函数和缩小类型的函数,如果断言失败,函数将抛出异常,这对于在运行时验证数据并同时保证Typescript正常运行。
ts
function assertDefined<T>(value: T | undefined): asserts value is T {
if (value === undefined) {
throw new Error('value is undefined')
}
}
// 自定义类型谓词 (asserts value is T)是语法
// 使用
function processUser(user: User | undefined) {
assertDefined(user)
console.log(user.name)
}
12. 名义类型模式(品牌类型模式)
这种模式是将相同类型但是又需要有区别人为制造差异化,定义一个_brand
虚拟属性,从而实现类型定义更准确。
ts
type UserId = string & {_brand: 'UserId'}
type PostId = string & {_brand: 'PostId'}
function createUserId(id: string): UserId {
return id as UserId
}
function createPostId(id: string): PostId {
return id as PostId
}
const userId: UserId = createUserId('12345')
const postId: PostId = createPostId('12345')
function getUserById(id: UserId) { /** */ }
getUserById(userId) // 正确
getUserById(postId) // 报错
13. 使用枚举
ts
const enum status = {
Error = 'error'
Success = 'success'
Fail = 'fail'
}
14. 组合交叉类型
将多个类型合并为一个类型,对于合并不相关的类型比extends好用
ts
type Name = string
type Age = number
type Worker = {
address: string,
job: string
}
type User = Name & Age & Worker
总结
运用好类型判断,不仅能节省排除错误的时间,还能提高开发效率,虽然定义类型是一件痛苦的事情,但是后续项目维护起来那就是非常丝滑的操作了。后续如果有补充再继续完善!