前言TS最好用的地方就是强类型,随之而来的就是类型窄化,摸鱼的时候顺道总结下.
类型推论TypeScript里,在有些没有明确指出类型的地方,类型推论会帮助提供类型 Example: let x = [0, 1, null] // numberlet x = Math.random() < 0.5 ? 100 : "helloword" // number|stringlet x: Animal[] = [new Rhino(), new Elephant(), new Snake()]; // Rhino | Elephant | Snake 如果没有找到最佳通用类型的话,类型推断的结果为联合数组类型 联合类型和类型守卫 Example: // 联合类型type Types = number | stringfunction typeFn(type: Types, input: string): string { // 如果这样写就需要判断type的类型} 可以直接赋值类型推断 let x:number|string = 1x="tiedan" 如果不判断会报错 function typeFn(type: number | string, input: string) { // 报错 运算符+号不能应用于 string return new Array(type + 1).join("") + input} 所以还得判断 function typeFn(type: number | string, input: string) { // 类型守卫 if (typeof type === 'number') { return new Array(type + 1).join(" ") + input } return type + input} 类型的窄化就是根据判断类型重新定义更具体的类型 那么问题来了学这玩意干嘛? js不香吗? 个人观点: 使用 TypeScript 可以帮你降低 JavaScript 弱语言的脆弱性,帮你减少由于不正确类型导致错误产生的风险,以及各种 JavaScript 版本混杂造成错误的风险。 TypeScript 只是把高级语言的强类型这个最主要的特征引入 JavaScript ,就解决了防止我们在编写 JavaScript 代码时因为数据类型的转换造成的意想不到的错误,增加了我们排查问题的困难性。 typeof的类型守卫: "string""number""bigint" // ES10新增"boolean""symbol" // ES6新增"undefined""object""function" 注意: typeof null 等于 object 因此: function strOrName(str: string | string[] | null) { if (typeof str === 'object') { for (const s of str) { // 报错 因为str有可能是null console.log(s) } } else if (typeof str === 'string') { console.log(str) } else { //...... }}
真值窄化js的真值表很复杂, 除以下的是false其余的都是真。 0NAN""0n // 0的bigint版本nullundefined 避免null的错误可以利用真值窄化 // 利用真值判断if (str && typeof strs === 'object') { for (const s of strs) { console.log(s) }} 或者这样也行 function valOrName(values: number[] | undefined, filter: number): number[] | undefined { if (!values) { return values } else { return values.filter(x => x > filter) }} 小结: 真值窄化帮助我们更好的处理null/undefined/0 等值
相等性窄化想等性窄化就是利用 ===、 !== 、==、and、!= 等运算符进行窄化 Example1: function strOrNum(x: string | number, y: string | boolean) { if (x === y) { // string } else { // string|number }} Example2: function strOrName(str: string | string[] | null) { if (str !== null) { if (typeof str === 'object') { for (const s of str) { console.log(s) // [] } } else if (typeof str === 'string') { console.log(str) // string } else { // ..... } }} Example3: interface Types { value: number | null | undefined}function valOrType(type: Types, val: number) { // null和undefined 都是false 只能是number if (type.value != null) { type.value *= val }}
in操作符窄化in是检查对象中是否有属性,现在充当了一个 "type guard" 的角色。 Example: interface A { a: number };interface B { b: string };function foo(x: A | B) { if ("a" in x) { return x.a; } return x.b;}
instanceof窄化instanceof表达式的右侧必须属于类型 any,或属于可分配给 Function接口类型的类型。 Example: function dateInval(x: Date | string) { if (x instanceof Date) { // Date } else { // string }}
窄化的本质窄化的本质是重新定义类型 Example: function example() { let x: string | number | boolean x = Math.random() < 0.5 if (Math.random() < 0.5) { x = 'hello' // string } else { x = 100 // number } return x; // string|number}
联合类型的窄化Example1: interface Shape { kind: "cirle" | "square", redius?: number sideLength?: number}// 报错function getArea(shape: Shape) { return Math.PI * shape.redius ** 2}// 窄化还是报错function getArea(shape: Shape) { if (shape.kind === 'cirle') { return Math.PI * shape.redius ** 2 }}// 利用非空断言阔以function getArea(shape: Shape) { if (shape.kind === 'cirle') { return Math.PI * shape.redius! ** 2 }} Example2: interface Circle { kind: "cirle"; redius: number;}interface Square { kind: "square"; redius: number;}type Shape = Circle | Squarefunction getArea(shape: Shape) { if (shape.kind === 'cirle') { // 窄化 return Math.PI * shape.redius ** 2 }}// 或者function getArea(shape: Shape) { switch (shape.kind) { case "cirle": return Math.PI * shape.redius ** 2 case "square": return shape.sideLength ** 2 default: const _example: never = shape return _example }}
总结到此这篇关于TypeScript学习笔记之类型窄化篇的文章就介绍到这了,更多相关TypeScript类型窄化内容请搜索wanshiok.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持wanshiok.com! React全局状态管理的三种底层机制探究 Vue.js slot插槽的作用域插槽用法详解 |