TS 进阶练习
TS内容进阶,紧随上篇文章 https://www.cnblogs.com/jickma/p/18025212 TS 学习随笔
学习内容源自 https://blog.csdn.net/weixin_44441196/article/details/123570019?spm=1001.2014.3001.5501
练习1 将接口中属性修改为只读
1 /** 2 * 将接口中属性修改为只读 3 */ 4 interface Person { 5 name: string, 6 age: number, 7 readonly phone: number 8 } 9 /** 10 * 完全看不懂什么用法, 11 * 按照我的理解就是创建了一个新的 接口,这个接口叫 ReadOnlyPerson 可以用这个接口创建新的对象 12 * 接口中的属性是 Person 中的属性,通过 in keyof(猜测类似于js 对象循环的方法)重新定义的属性 13 * name: string, 可以理解为 key为name ,value为string 14 * [P in keyof Person]为 key,Person[P]为value 15 * 而 readonly 为修饰符,表示只读 16 * type 应该为一个关键字,表示创建一个新接口 17 */ 18 type ReadOnlyPerson = { 19 readonly [P in keyof Person]: Person[P] 20 } 21 let personOne: Person = { 22 name: '张三', 23 age: 24, 24 phone: 1234567890 25 } 26 personOne.name = '王五' 27 let personTwo: ReadOnlyPerson = { 28 name: '李四', 29 age: 26, 30 phone: 190000 31 } 32 // personTwo.name = '赵云' // 报错 无法为“name”赋值,因为它是只读属性。 33 /** 34 * 在代码书写完成之后就会直接报错,并无法运行, 35 * 在js中对象是没有只读这样的属性的, 36 * 编译成功之后的js仅为两个名叫 personOne personTwo 的两个对象 37 * 以及对name值得修改 38 */ 39 // console.log(personOne, 'personOne'); // { name: '王五', age: 24, phone: 1234567890 } personOne 40 // console.log(personTwo, 'personTwo'); // { name: '李四', age: 26, phone: 190000 } personTwo
练习2 将某个 interface 里的索引全部转为联合类型
1 /** 2 * 将某个 interface 里的索引全部转为联合类型 3 */ 4 /** 5 * 联合类型 就是用| 将多个类型组合在一起, 6 * 在定义变量类型时候有遇到 7 */ 8 // 这便是联合类型 9 // let strOrNum: number | string = '张飞' 10 // strOrNum = 123456 11 interface Animal { 12 name: string, 13 age: number, 14 readonly phone: number 15 } 16 type UnionTypes = keyof Animal 17 /** 18 * 试了一些方法,但是始终无法输出正确得联合类型数据 别人得贴子输出是这样的 19 * 'name' | 'age' | 'gender' 20 * UnionTypes 是无法直接输出得 直接输出报错 “UnionTypes”仅表示类型,但在此处却作为值使用。 21 */ 22 let typeAAA: UnionTypes = "name" // 网上说这个地方会显示 UnionTypes 得可选值,我的没有出现 23 // console.log(typeAAA,'typeAAA'); // name
练习3 将两个interface组成一个新的interface
1 /** 2 * 将两个interface组成一个新的interface 3 */ 4 interface type1 { 5 name: string 6 readonly age: number 7 } 8 interface type2 { 9 adress: string 10 } 11 type type3 = type1 & type2 12 /** 13 * type1 中没有adress这个属性 14 * 语法错误。 15 * 对象字面量只能指定已知属性,并且“adress”不在类型“type1”中。 16 */ 17 // let typeAll1: type1 = { 18 // name: '景天', 19 // age: 24, 20 // adress: '永安当' // 对象字面量只能指定已知属性,并且“adress”不在类型“type1”中。 21 // } 22 let typeAll: type3 = { 23 name: '景天', 24 age: 24, 25 adress: '永安当' 26 } 27 // console.log(typeAll, 'typeAll'); // { name: '景天', age: 24, adress: '永安当' } 28 interface type4 { 29 // name: number 30 adress: string 31 phone: number 32 } 33 type type5 = type1 & type2 & type4 34 /** 35 * 由此可以推断出,这个地方可以无限制合并 36 * 如果属性有相同得 并且type值也相同,没有问题,并不会显示两个 adress 37 * 如果type不同 就会报错 不能将类型“string”分配给类型“never”。 38 * 如 name 上面是 string类型,下边是 number类型,无论我在赋值时候写什么都是显示这句话 39 */ 40 let typeAllKey: type5 = { 41 name: '茂山', 42 age: 23, 43 adress: '永安当', 44 phone: 132456 45 } 46 // console.log(typeAllKey, 'typeAllKey'); // { name: '茂山', age: 24, adress: '永安当', phone: 132456 }
练习4 利用 pick 从一个interface中选择索引生成新的interface 利用 Omit 从一个interface中排除部分择索引生成新的interface
1 /** 2 * 利用 pick 从一个interface中选择索引生成新的interface 3 * 利用 Omit 从一个interface中排除部分择索引生成新的interface 4 * pick Omit 可以理解为返回某些数据和不返回某些数据 5 * pick 在已经定义的对象中选取一些 pick<T,keys> T表示选择谁的属性 keys表示选择哪几个属性(传入属性名,只能是第一个 类型变量中存在的属性) 6 * Omit 在已经定义的对象中删除一些 Omit<T,keys> 7 * 除了这两个还有 Exclude(排除/不包括) Extract (提取/包括) 这两个用法与 pick Omit 不同,暂时未测试 8 */ 9 interface car { 10 name: string 11 width: number 12 height: number 13 weight: number | string 14 speed: number | string 15 } 16 // 现在有一个新的车,这个车只有长宽, 17 type onlyHasWH = Pick<car, 'width' | 'height'> 18 let onlyHasWHObj: onlyHasWH = { 19 // name: '凯迪拉克', // 语法错误 对象字面量只能指定已知属性,并且“name”不在类型“onlyHasWH”中。 20 width: 120, 21 height: 490 22 } 23 // console.log(onlyHasWHObj); // { width: 120, height: 490 } 24 // 现在又有一个新车,这个车除了长宽其余得都有 25 type onlyNoWH = Omit<car, 'width' | 'height'> 26 let onlyNoWHObj: onlyNoWH = { 27 name: '凯迪拉克', 28 // width: 120, // 语法错误 对象字面量只能指定已知属性,并且“width”不在类型“onlyNoWH”中。 29 // height: 490 30 weight: '120kg', 31 speed: '200km/h' 32 } 33 // console.log(onlyNoWHObj); // { name: '凯迪拉克', weight: '120kg', speed: '200km/h' }
练习5 利用InstanceType从一个类里面获取interface
1 /** 2 * 利用InstanceType从一个类里面获取interface 3 * InstanceType 接受一个类类型作为参数,并返回该类的实例类型。 4 */ 5 class person { 6 name: string 7 age: number 8 readonly sex: string = '男' 9 constructor(name: string, age: number) { 10 this.name = name 11 this.age = age 12 } 13 } 14 // InstanceType 就是把一个类中得属性拿出来了,然后可以单独用作一个新的对象 对于只读属性,是可以直接修改得 15 type newPerson = InstanceType<typeof person> 16 let a: newPerson = { 17 name: '李淳风', 18 age: 89, 19 sex: '女' 20 }
练习6 利用Parameters从函数的参数中推导出类型 利用ReturnType从函数的返回值中推导出类型
1 /** 2 * 利用Parameters从函数的参数中推导出类型 3 * 利用ReturnType从函数的返回值中推导出类型 4 * 这两个是从函数里面获取参数类型与返回值得类型 5 * 在函数中入参类型确定之后,返回值类型也就能确定了 6 */ 7 function foo1(v: string, b: number) { 8 return v + b 9 } 10 let foo2 = (v: string, b: number) => { 11 return v + b 12 } 13 // 函数这两种写法是一样得,没有差别都可以使用 14 type parame1 = Parameters<typeof foo1> 15 // 得出来的是一个数组 parame1 [v: string, b: number] 如果参数再多,那数组长度增加 16 let a1: parame1 = ['1', 1] // 如果写别类型的就会报语法错误,比如说布尔值 17 type parame2 = ReturnType<typeof foo1> 18 // 最终结果得到的是一个 字符串 19 let a2:parame2 = '111' // 如果写别的类型就会报语法错误