Typescript 实战 --- (8)高级类型
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Typescript 实战 --- (8)高级类型,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5155字,纯文字阅读大概需要8分钟。
内容图文

类型1 & 类型2 & 类型3
interface CatInterface { run(): void } interface DogInterface { jump(): void } // 交叉类型具有所有类型的特性 let pet: CatInterface & DogInterface = { run() {}, jump() {} }
let a: number | string = 2; a = ‘hello‘; a = undefined; // 可以为其子类型 a = true; // Error: 不能将类型“true”分配给类型“string | number”
// 字符串联合类型 let x: ‘typescript‘ | ‘webpack‘ | ‘nodejs‘; x = ‘webpack‘; x = ‘hello‘; // Error: 不能将类型“"hello"”分配给类型“"typescript" | "webpack" | "nodejs"”// 数字联合类型 let y: 1 | 2 | 3; y = 3; y = 33; // Error: 不能将类型“33”分配给类型“1 | 2 | 3” let z: ‘typescript‘ | 2; z = ‘typescript‘; z = 2; z = 1; // Error: 不能将类型“1”分配给类型“"typescript" | 2”
enum Pet { Dog, Cat }; interface DogInterface { run(): void ; eat(): void ; } interface CatInterface { jump(): void ; eat(): void ; } class Dog implements DogInterface { run() {}; eat() {}; } class Cat implements CatInterface { jump() {}; eat() {}; } function getPet(pet: Pet) { // let smallPet: Dog | Cat let smallPet = pet === Pet.Dog ? new Dog() : new Cat(); // 类型不确定时,只能取公有成员 smallPet.eat(); smallPet.run(); // 类型“Dog | Cat”上不存在属性“run” smallPet.jump(); // 类型“Dog | Cat”上不存在属性“jump”return smallPet; }
// 例如:Shape是多个类型的联合类型,每个类型都具有一个公共属性kind,由此在 switch中建立了不同类型的保护区块 interface Rectangle { kind: ‘rectangle‘; width: number; height: number; } interface Square { kind: ‘square‘; size: number; } type Shape = Rectangle | Square; function area(s: Shape) { switch(s.kind) { case ‘rectangle‘: return s.width * s.height; case ‘square‘: return s.size * s.size; } }
如果又添加了一个联合类型,但是又没有在 area 函数中设定类型保护区块,会发生什么呢?
interface Rectangle { kind: ‘rectangle‘; width: number; height: number; } interface Square { kind: ‘square‘; size: number; } // 添加新的联合类型interface Circle { kind: ‘circle‘; r: number; } type Shape = Rectangle | Square | Circle; function area(s: Shape) { switch(s.kind) { case ‘rectangle‘: return s.width * s.height; case ‘square‘: return s.size * s.size; } } console.log(area({ kind: ‘circle‘, r: 1 })); // undefined
执行程序打印出了一个结果 undefined,由于上例中并没有在 area 方法中为 Circle 指定计算面积的方法,理论上应该提示错误,而不是直接返回 undefined。
为了让编译器正确的提示错误,有两种可选方法:
(1)、为 area 方法指定返回值类型
function area(s: Shape): number { switch (s.kind) { case ‘rectangle‘: return s.width * s.height; case ‘square‘: return s.size * s.size; } }
(2)、利用never类型
// 给定一个 default 分支,通过判断 s 是不是 never 类型来提示错误。 // 如果是 never 类型,则可以在前面的分支中找到对应的执行代码; // 如果不是 never 类型,则说明前面的代码有遗漏,需要补全 function area(s: Shape): number { switch (s.kind) { case ‘rectangle‘: return s.width * s.height; case ‘square‘: return s.size * s.size; default: return ((e: never) => { thrownew Error(e) })(s); // 类型“Circle”的参数不能赋给类型“never”的参数 } }
通过错误提示补全代码
function area(s: Shape): number { switch (s.kind) { case ‘rectangle‘: return s.width * s.height; case ‘square‘: return s.size * s.size; case ‘circle‘: return Math.PI * s.r ** 2 default: return ((e: never) => { thrownew Error(e) })(s); } } console.log(area({ kind: ‘circle‘, r: 1 })); // 3.141592653589793
3、索引类型
使用索引类型,编译器就能够检查使用了动态属性名的代码。例如:从js对象中选取属性的子集,然后建立一个集合
let obj = { a: 1, b: 2, c: 3 } function getValues(obj: any, keys: string[]) { return keys.map(key => obj[key]) } // obj 中存在的属性 console.log(getValues(obj, [‘a‘, ‘b‘])); // [ 1, 2 ]// obj 中不存的属性,返回 undefined,而没有提示报错 console.log(getValues(obj, [‘e‘, ‘f‘])); // [ undefined, undefined ]
索引类型可以用来解决上例中的问题,在认识索引类型之前需要先了解几个概念:
(1)、索引类型查询操作符 keyof T
对于任何类型T,keyof T 的结果是 类型T的所有公共属性的字面量的联合类型
interface Person { name: string; gender: string; age: number; } let personProps: keyof Person; // ‘name‘ | ‘gender‘ | ‘age‘ console.log(personProps)
(2)、索引访问操作符 T[K]
interface Person { name: string; gender: string; age: number; } let n: Person[‘name‘]; // n 的类型是 string let a: Person[‘age‘]; // a 的类型是 number
// 1、用T来约束obj // 2、用K来约束keys数组 // 3、给K增加一个类型约束,让它继承obj的所有属性的联合类型 // 4、函数的返回值是一个数组,数组的元素的类型就是属性K对应的类型 let obj = { a: 1, b: 2, c: 3 } function getValues<T, K extends keyof T>(obj: T, keys: K[]): T[K][] { return keys.map(key => obj[key]) } // obj 中存在的属性 console.log(getValues(obj, [‘a‘, ‘b‘])); // [ 1, 2 ] console.log(getValues(obj, [‘e‘, ‘f‘])); // Error:不能将类型“string”分配给类型“"a" | "b" | "c"”
4、映射类型
interface Obj { a: string; b: number; c: boolean ; }
4-1、同态
同态的意思是:只会作用于旧类型的属性,而不会引入新的属性
(1)、Readonly<T> 将旧类型中的每一个成员都变成只读
type ReadonlyObj = Readonly<Obj>;
(2)、Partial<T> 把旧类型中的每一个成员都变成可选的
type PartialObj = Partial<Obj>;
(3)、Pick<T, key1 | key2 | keyn> 可以抽取旧类型中的一些子集
接受两个参数:第一个是要抽取的对象,第二个是要抽取的属性的key
type PickObj = Pick<Obj, ‘a‘ | ‘c‘>;
4-2、非同态,会创建一些新的属性
(1)、Record<key1 | key2 | keyn, T>
接受两个参数:第一个参数是一些预定义的新的属性,第二个参数是一个已知的对象
type RecordObj = Record<‘x‘ | ‘y‘, Obj>;
原文:https://www.cnblogs.com/rogerwu/p/12214808.html
内容总结
以上是互联网集市为您收集整理的Typescript 实战 --- (8)高级类型全部内容,希望文章能够帮你解决Typescript 实战 --- (8)高级类型所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。