typescript修炼指南(四)
大纲
本章主要是一些ts的类型工具以及模块化和相关实践,涉及以下内容:
类型编程
module和namespace
小技巧
ts在react中的实践
这篇稍微有点零碎,建议多查阅文档或者查阅相关的文章进行更多的了解,代码示例以告知 QAQ
往期推荐:
typescript修炼指南(一)
typescript修炼指南(二)
typescript修炼指南(三)
类型编程
索引类型(假定我们要取出如下对象的name属性对应的值)
const user = {
name: 'lili',
age: 20,
sex: 'woman',
}
// 声明类型
interface User {
[key: string]: any
}
function choose(obj: User, key: string[]): any[] {
return key.map(item => obj[item]) // 返回对应属性的值 返回的是数组
}
choose(user, ['name'])
索引类型查询操作符
class Person1 {
public name: string = 'lili'
public age: number = 20
}
type getTypePerson = keyof Person1
interface Point {
x: number;
y: number;
}
// type keys = "x" | "y"
type keys = keyof Point;
索引访问操作符 T[K][], 之前也提到过
function Person2(obj: T, name: K[]): T[K][] {
return name.map(item => obj[item])
}
const User2 = { name: 'lili', age: 20}
Person2(User2, ['name', 'age'])
// 以下是代码提示: (相对更加严谨)
// (local function) Person2<{
// name: string;
// age: number;
// }, "name" | "age">(obj: {
// name: string;
// age: number;
// }, name: ("name" | "age")[]): (string | number)[]
映射类型 [K in keyof T]
interface User3interface {
name: string,
age: number,
}
// 添加每个都为可选类型
type User3 = {
[K in keyof T]?: T[K]
}
type User3s = User3
// 代码提示:
// type User3s = {
// name?: string | undefined;
// age?: number | undefined;
// }
截获函数返回值类型 ---- ReturnType
interface User4Interface {
name: string,
age: number,
}
type UserType = () => User4Interface
type User4 = ReturnType // User4Interface
类型递归
interface Other {
hobby: string,
sex: string,
}
interface User5 {
name: string,
age: number,
other: Other
}
// 为每个类型添加一个可选类型
// 1. 类型工具 Partial
type U1 = Partial
// 代码提示:
// type U1 = {
// name?: string | undefined;
// age?: number | undefined;
// other?: Other | undefined;
// }
// 2. 手动实现
type Particals = {
[U in keyof T]?: T[U] extends object ? Particals : T[U]
}
type U2 = Particals
// type U2 = {
// name?: string | undefined;
// age?: number | undefined;
// other?: Particals | undefined;
// }
工具类型
’+‘号 ’-‘号 这两个关键字用于映射类型中给属性添加修饰符,比如-?就代表将可选属性变为必选,-readonly代表将只读属性变为非只读。比如TS就内置了一个类型工具Required,它的作用是将传入的属性变为必选项:
Required 将传入的属性变为必选项
type Required = { [P in keyof T]-?: T[P] };
Exclude 的作用是从 T 中排除出可分配给 U的元素. T extends U指T是否可分配给U
type Exclude = T extends U ? never : T;
type T = Exclude<1 | 2, 1 | 3> // -> 2
Omit
type Omit = Pick>
type Foo = Omit<{name: string, age: number}, 'name'> // -> { age: number }
Merge Merge的作用是将两个对象的属性合并:
// type Merge = Compute + Omit
// type obj3 = Merge
type obj1 = {
name: string,
age: number
}
type obj2 = {
sex: string,
hobby?: string,
}
type Compute =
A extends Function
? A
: { [K in keyof A]: A[K] }
type obj3 = Compute
// type obj3 = {
// name: string;
// age: number;
// sex: string;
// hobby?: string | undefined;
// }
Intersection Intersection是Extract与Pick的结合,Intersection = Extract + Pick
type obj4 = {
name: string,
age: number,
}
type obj5 = {
name: string,
sex: string,
}
type Intersection = Pick & Extract> // Extract 提取
type obj6 = Intersection
// type obj6 = {
// name: string;
// }
Overwrite顾名思义,是用U的属性覆盖T的相同属性.
type obj7 = {
name: string,
age: number,
}
type obj8 = {
name: number,
}
// import { Diff } from 'utility-types' 要安装一下库
type Overwrite & Intersection> = Pick
type obj9 = Overwrite
// type obj9 = {
// name: number; --- 被重写了
// age: number;
// }
// Mutable 将 T 的所有属性的 readonly 移除
type Mutable = {
-readonly [P in keyof T]: T[P]
}
type ob = {
readonly name: string,
age: number,
}
type obj10 = Mutable
// type obj10 = {
// name: string;
// age: number;
// }
module和namespace
全局变量
比如在1.ts定义:const a = 1, 2.ts定义: const a = 2 这样全局中定义的变量会报错 因为重复声明了 避免全局变量
导出类型
export type User = {
name: string,
age: number,
}
导出多个类型
// 导出多个类型
type User1 = {
name: string,
age: number,
}
interface User2 {
name: string,
age: number,
}
// "isolatedModules": false, tsconfig.json 要设置一下
export { User1, User2 }
重命名
export { User1 as user1 }
引入
import { User2 as user2 } from './module';
// 整体导入
import * as u from './module';
// 同样的 --- 默认导出
export default () => {
}
namespace
其实一个命名空间本质上一个对象,它的作用是将一系列相关的全局变量组织到一个对象的属性
如果一个命名空间在一个单独的 TypeScript 文件中,则应使用三斜杠 /// 引用它,语法格式如下:
// index.ts
// 声明全局的明明空间
declare namespace USER {
// 导出接口
export interface find { (name: string): string }
export interface create { (name: string): string }
export interface update { (name: string): string }
export interface deleted { (name: string): string }
}
// 引入文件
///
// 使用命名空间的模块
interface API {
USER: {
update: USER.update
// .....
},
}
小技巧
注释,利于智能提示快速定位代码
interface User {
/**
* 用户
*/
name: string,
age: number,
}
const user: User = { name: 'lili', age: 20 }
// 以下是代码提示
// (property) User.name: string
// 用户
类型推导
function getUser(name: string): string {
return name
}
// typeof 获取整体函数的类型
type getU = typeof getUser
// type getU = (name: string) => string
// h获取返回值的类型
type returnT = ReturnType
// type returnT = string
巧用Omit
有时候我们需要复用一个类型,但是又不需要此类型内的全部属性,因此需要剔除某些属性,这个时候 Omit 就派上用场了。
interface User1 {
name: string,
age: number,
sex: string,
}
type newUser1 = Omit
// type newUser1 = {
// name: string;
// age: number;
// }
Record 高级类型
Record 允许从 Union 类型中创建新类型,Union 类型中的值用作新类型的属性。有利于类型安全
type List = 'u1' | 'u2' | 'u3'
// 要求用户表的属性必须包含 { name: string, age: number } 类型字段
type UserList = Record
-
const userList: UserList = {
u1: { name: 'lili', age: 20 },
u2: { name: 'xiaoming', age: 21 },
u3: { name: 'xiaohong', age: 22 },
}
react实践
编写一个无状态的组件
写法1:
// 定义一个接口
interface Rrop {
/**
* 这是一个react组件的属性
*/
name: string,
age: number,
}
// 无状态组件
export const comp: React.SFC
name: {name} age: {age}
)
}
写法2:
type Props1 = {
click(e: React.MouseEventhello
)
}
}
ref
interface Props {
name: string,
age: number,
}
interface State {
name: string,
}
export class StateComp extends React.Component{this.state.name}
this.onChangeInput(e)}/>
>
)
}
}
默认属性传递
interface Other {
hobby? : string
}
class ClassProp {
public name: string = ''
public submit = (name: string): string => name
public other: Other = {
hobby: ''
}
}
// 实例化类传递 默认属性
export class PropsClass extends React.Component{ name } { other.hobby}
)
}
}
promise类型问题
// promise类型问题
interface propP
发表评论 (审核通过后显示评论):