TypeScript學(xué)習(xí)筆記之類型窄化篇
前言
TS最好用的地方就是強(qiáng)類型,隨之而來的就是類型窄化,摸魚的時(shí)候順道總結(jié)下.
類型推論
TypeScript里,在有些沒有明確指出類型的地方,類型推論會(huì)幫助提供類型
Example:
let x = [0, 1, null] // number let x = Math.random() < 0.5 ? 100 : "helloword" // number|string let x: Animal[] = [new Rhino(), new Elephant(), new Snake()]; // Rhino | Elephant | Snake
如果沒有找到最佳通用類型的話,類型推斷的結(jié)果為聯(lián)合數(shù)組類型
聯(lián)合類型和類型守衛(wèi)
Example:
// 聯(lián)合類型 type Types = number | string function typeFn(type: Types, input: string): string { // 如果這樣寫就需要判斷type的類型 }
可以直接賦值類型推斷
let x:number|string = 1 x="tiedan"
如果不判斷會(huì)報(bào)錯(cuò)
function typeFn(type: number | string, input: string) { // 報(bào)錯(cuò) 運(yùn)算符+號(hào)不能應(yīng)用于 string return new Array(type + 1).join("") + input }
所以還得判斷
function typeFn(type: number | string, input: string) { // 類型守衛(wèi) if (typeof type === 'number') { return new Array(type + 1).join(" ") + input } return type + input }
類型的窄化就是根據(jù)判斷類型重新定義更具體的類型
那么問題來了學(xué)這玩意干嘛? js不香嗎?
個(gè)人觀點(diǎn):
使用 TypeScript 可以幫你降低 JavaScript 弱語言的脆弱性,幫你減少由于不正確類型導(dǎo)致錯(cuò)誤產(chǎn)生的風(fēng)險(xiǎn),以及各種 JavaScript 版本混雜造成錯(cuò)誤的風(fēng)險(xiǎn)。
TypeScript 只是把高級(jí)語言的強(qiáng)類型這個(gè)最主要的特征引入 JavaScript ,就解決了防止我們?cè)诰帉?JavaScript 代碼時(shí)因?yàn)閿?shù)據(jù)類型的轉(zhuǎn)換造成的意想不到的錯(cuò)誤,增加了我們排查問題的困難性。
typeof的類型守衛(wèi):
"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) { // 報(bào)錯(cuò) 因?yàn)閟tr有可能是null console.log(s) } } else if (typeof str === 'string') { console.log(str) } else { //...... } }
真值窄化
js的真值表很復(fù)雜, 除以下的是false其余的都是真。
0 NAN "" 0n // 0的bigint版本 null undefined
避免null的錯(cuò)誤可以利用真值窄化
// 利用真值判斷 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) } }
小結(jié): 真值窄化幫助我們更好的處理null/undefined/0 等值
相等性窄化
想等性窄化就是利用 ===、 !== 、==、and、!= 等運(yùn)算符進(jìn)行窄化
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是檢查對(duì)象中是否有屬性,現(xiàn)在充當(dāng)了一個(gè) "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表達(dá)式的右側(cè)必須屬于類型 any,或?qū)儆诳煞峙浣o Function接口類型的類型。
Example:
function dateInval(x: Date | string) { if (x instanceof Date) { // Date } else { // string } }
窄化的本質(zhì)
窄化的本質(zhì)是重新定義類型
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 }
聯(lián)合類型的窄化
Example1:
interface Shape { kind: "cirle" | "square", redius?: number sideLength?: number } // 報(bào)錯(cuò) function getArea(shape: Shape) { return Math.PI * shape.redius ** 2 } // 窄化還是報(bào)錯(cuò) 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 | Square function 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 } }
總結(jié)
到此這篇關(guān)于TypeScript學(xué)習(xí)筆記之類型窄化篇的文章就介紹到這了,更多相關(guān)TypeScript類型窄化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jq.ajax+php+mysql實(shí)現(xiàn)關(guān)鍵字模糊查詢(示例講解)
下面小編就為大家分享一篇jq.ajax+php+mysql實(shí)現(xiàn)關(guān)鍵字模糊查詢(示例講解),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01ajax前臺(tái)后臺(tái)跨域請(qǐng)求處理方式
本篇文章通過前臺(tái)跨域請(qǐng)求處理以及后臺(tái)跨域的數(shù)據(jù)處理方式介紹,詳細(xì)分析了ajax跨域的問題,對(duì)此有需要的朋友學(xué)習(xí)下。2018-02-02Rollup處理并打包JS文件項(xiàng)目實(shí)例代碼
rollup是一款用來es6模塊打包代碼的構(gòu)建工具(支持css和js打包)。這篇文章主要介紹了Rollup處理并打包JS文件項(xiàng)目實(shí)例,需要的朋友可以參考下2018-05-05js表單提交和submit提交的區(qū)別實(shí)例分析
這篇文章主要介紹了js表單提交和submit提交的區(qū)別,結(jié)合實(shí)例形式較為詳細(xì)的分析了js表單提交和submit提交具體實(shí)現(xiàn)方法與使用技巧,需要的朋友可以參考下2015-12-12