likes
comments
collection
share

深入了解Typescript语法,Record,Partial,Pick等

作者站长头像
站长
· 阅读数 12

前言

相信大家对Typescript的基本语法一定略知一二,但想往更高处发展就必须了解一些更高级的用法。在项目中如果能运用到这些高级语法,那么一定会事半功倍。闲话不多说,让我们开启今天的学习吧。

联合类型(UnionType)

首先是联合类型的介绍,也是一切的起源。

let a: string | number | boolean = '123' // 变量a的类型既可以是string,
a = 123 // 也可以是number
a = true // 也可以是boolean

keyof

将一个类型的属性名全部提取出来当做联合类型

// key of 使用
interface People {
    name: string;
    age: number;
}
// keyof 取 interface 的键
// type keys = "name" | "age"
type keys = keyof People;
// 假设有一个 object 如下所示,
// 我们需要使用 typescript 实现一个 get 函数来获取它的属性值
const xiaozhang:People = {
    name: '小张',
    age: 12
}

function get<T extends object, K extends keyof T>(o: T, name: K): T[K] {
    return o[name]
}
console.log(get(xiaozhang,'age')) // 12
console.log(get(xiaozhang,'name')) // 小张
// error 类型“"address"”的参数不能赋给类型“keyof People”的参数。
console.log(get(xiaozhang,'address'))

keyof 与 Object.keys 略有相似,只不过 keyof 取 interface 的键

映射(Record)

Record用于属性映射

定义一个普通的对象类型

// {[x: string]: any;}
type Myobject = Record<string, any>
let a:Myobject = {
    x1:'aaa'
}

搭配联合类型

type RequestMethods = 'GET'|'POST'| 'DELETE'
type MethodsAny = Record<RequestMethods, any>
let mothod1:MethodsAny = {
    GET:"1",
    POST:'1',
    DELETE:'1'
}
let mothod2:MethodsAny = {
    GET:"1",
    POST:'1',
    DELETE:'1',
    PUT:'111' // error “PUT”不在类型“MethodsAny”中
}

搭配接口

interface PersonModel {
    name:string,
    age:number
}
// [x: string]: PersonModel;
type student = Record<string, PersonModel>

let students:student = {
    student1:{
        name:'小凌',
        age:18
    },
    student2:{
        name:'小李',
        age:19
    }
}

Partial(转化可选参数)

ts中就是让一个定义中的所有属性都变成可选参数

// Partial
interface People {
    name: string;
    age: number;
}

// 报错 类型“{}”缺少类型“People”中的以下属性: name, age
const person1: People = {}

/**
  那这个时候我们就可以用到typescript自带的高级类型 Partial,就相当于将上方接口所有属性变成可选的
  将我们需要定义的类型当做泛型传入Partial中,那么就相当于当前的类型里面的所有属性都是可选的
 */
const person2: Partial<People> = {} // 可以
const person3: Partial<People> = { name: 'xiaodu' } // 可以
const person4: Partial<People> = { sex: '男' } // 报错 “sex”不在类型“Partial<People>”中

Required(转换必须参数)

Partial刚好相反,将一个定义中的属性全部变成必选参数

// 必选参数
interface People {
    name?: string;
    age?: number;
}
// 类型 "{ name: string; }" 中缺少属性 "age",但类型 "Required<People>" 中需要该属性 
const person2: Required<People> = {
    name:"11"
}

Pick(选择)

ts中可以选择一个原来的接口中一部分的属性定义

interface People {
    name: string
    age: number
}

type somePeople = Pick<People,'name'>

let onlyName:somePeople = { // 可以
    name:"112" 
}

Readonly (属性转换为只读)

ts中就是让一个定义中的所有属性都变成只读参数

// 只读
interface People {
    name: string
    age: number,
    dog:{
        name:string
        age:number
    }
}
const xiaoling: Readonly<People> = {
    name: '小凌', // 只读
    age: 18, // 只读
    dog:{
        age:1,
        name:'大黄'
    }
}
// 但是是浅层的。
xiaoling.name = '大凌' // 无法分配到 "name" ,因为它是只读属性。
xiaoling.dog.age = 2 // 可以

Exclude(排除)

ts中可以排除 联合类型 中一部分的内容 注意:Exclude用来操作联合类型

type havTypes = 'name' | 'age' | 'sex'
type someTypes = Exclude<havTypes,'sex'>
const myTypes1:someTypes = 'name' // 可以
const myTypes2:someTypes = 'sex' // 错误 不能将类型“"sex"”分配给类型“someTypes”。

Omit (省略)

ts中就是将接口或者类型的键值对删除一部分

// 省略
interface People {
    name: string;
    age: number;
}
type somePeople = Omit<People,'name'>
/**
 type somePeople = {
    age: number;
}
 */

ReadonlyArray(只读数组)

创建一个数组,数组中的索引不允许被修改

我们知道当我们使用const创建对象或者数组时,其实是可以修改其内部属性的,但是有的时候我们可能不需要其内部能够被修改,这时候我们就需要用ReadonlyArray了。

实现的方式有两种:

// 方法1:通过类型断言的方式
const arr = ['小伟','小铁','小涵','小凌'] as const
arr[3] = '帅哥'; //  报错 无法分配到 "3" ,因为它是只读属性。
// 方法2:使用ReadonlyArray
const arr2 : ReadonlyArray<string> = ['木兰','盾山','凯','百里守约']
arr2[3] = '百里玄策' // 报错 类型“readonly string[]”中的索引签名仅允许读取。

你是不是就想知道as constReadonlyArray这两者的区别在哪里?【手动滑稽】

区别在于as const是深层次的,尽管数组内放的对象,对象内部数据也是不能被修改的。ReadonlyArray则是‘浅层’的。

as const

深入了解Typescript语法,Record,Partial,Pick等

ReadonlyArray

深入了解Typescript语法,Record,Partial,Pick等

可以看到修改ReadonlyArray数组内的第二层其实是可以的。

项目地址

以下是项目地址:ts项目地址