一些在实战中总结的TS小技巧
- 使用TS帮助获取对象的值
在定义页面路由时, 可能会遇到这种情况:
typescript
interface FileRoutesByPath {
"/": {
id: "/";
path: "/";
fullPath: "/";
};
"/about": {
id: "/about";
path: "/about";
fullPath: "/about";
};
}路由的数据是这种数据类型, 但是我们在页面上会更改数据结构, 使用其中的部分内容, 例如:
js
{
title: '/about',
to: '/about'
}此时我只想要根据前面的 fullPath 字段的值赋给 to 字段, 使用TS可以推导这个字段的值
typescript
type Menu<T> = T[keyof T] extends {fullPath: infer U} ? {
title: string
to: U
}[] : never
const menuT: MenuT<FileRoutesByPath> = [
{
title: '/',
to: '/'
},
{
title: '/about',
to: '' // <- 此时的to字段, 在编辑器里就会自动提示出所有fullPath的值
}
]- Union type 绑定关系 通过使用
Union类型来绑定关系, 例如: 在开发中, 遇到某些需要根据同级别其他属性的类型来绑定属性类型时,
typescript
type Person = {
name: string;
age: number;
gender: 'male' | 'female';
}这时如果 gener 是 male 的话, 需要新增一个 strength 属性, 如果是 female 的话, 需要一个 makeup 属性 如果用 ? 来表示这个属性是可选的, 就会在开发中发现两个属性都可以被编辑器提示
这时就可以用Union type解决
typescript
type Person = {
name: string;
age: number
} & ({
gender: 'male'
strength: number
} | {
gener: 'female'
makeup: string
})需要注意的是, 这个技巧TS中的工具类型例如: Omit, Pick等不起作用 需要自己实现一个:
typescript
type UnionOmit<T, K extends string | number | symbol> =
T extends unknown
? Omit<T, K>
: neveras const
通常使用一个 const 定义常量之后, 我们希望使用这个常量对象来获取他的值
例如:
typescript
const routes = {
home: '/',
about: '/'
}
const goToRoute = (route: "/" | "/about") => {};但是这是当我们想要使用 goToRoute(routes.admin) 时, 就会报错, 因为 routes.admin 的类型是 string.
为什么会这样呢?
因为 routes 是一个 const , 但是 routes.admin 是可以修改.
可以使用
typescript
const goToRoute = (route: "/" | "/about") => {};解决方式
就是使用 as const
typescript
const routes = {
home: '/',
about: '/'
} as const这样就可以使用 goToRoute(routes.admin) 了
Object.freeze?
用 Object.freeze呢?
typescript
const routes = Object.freeze({
home: '/',
about: '/'
})针对单层对象可以, 但是Object.freeze不会处理深层的属性, 例如:
typescript
const routes = Object.freeze({
home: '/',
about: '/',
deep: {
name: '/deep'
}
})
// 这一行不会报错
routes.deep.name = '/hello'获取 const 的值
typescript
const routes = {
home: '/',
about: '/about',
user: '/user'
} as const这时可以定义一个:
typescript
type TypeOfRoutes = typeof routes;此时 TypeOfRoutes的值就是变成了:
typescript
const routes = {
home: '/',
about: '/about',
user: '/user'
} as const
type TypeOfRoutes = typeof routes;
type Routes = (typeof routes)[keyof typeof routes]
/* _____________ Further Steps _____________ */
/*
> Share your solutions: https://tsch.js.org/1367/answer
> View solutions: https://tsch.js.org/1367/solutions
> More Challenges: https://tsch.js.org
*/
type TypeOfRoutes = {
readonly home: "/";
readonly about: "/about";
readonly user: "/user";
}再从 TypeOfRoutes中提取实际的value
typescript
type Routes = (typeof routes)[keyof typeof routes]那么 Routes就变成了 "/" | "/about" | "/user", 就可以直接使用这个type了
typescript
const goToRoute = (route: Route) => {}```