TypeScript學(xué)習(xí)筆記之類型窄化篇
前言
TS最好用的地方就是強類型,隨之而來的就是類型窄化,摸魚的時候順道總結(jié)下.
類型推論
TypeScript里,在有些沒有明確指出類型的地方,類型推論會幫助提供類型
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"
如果不判斷會報錯
function typeFn(type: number | string, input: string) {
// 報錯 運算符+號不能應(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不香嗎?
個人觀點:
使用 TypeScript 可以幫你降低 JavaScript 弱語言的脆弱性,幫你減少由于不正確類型導(dǎo)致錯誤產(chǎn)生的風(fēng)險,以及各種 JavaScript 版本混雜造成錯誤的風(fēng)險。
TypeScript 只是把高級語言的強類型這個最主要的特征引入 JavaScript ,就解決了防止我們在編寫 JavaScript 代碼時因為數(shù)據(jù)類型的轉(zhuǎn)換造成的意想不到的錯誤,增加了我們排查問題的困難性。
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) {
// 報錯 因為str有可能是null
console.log(s)
}
} else if (typeof str === 'string') {
console.log(str)
} else {
//......
}
}
真值窄化
js的真值表很復(fù)雜, 除以下的是false其余的都是真。
0 NAN "" 0n // 0的bigint版本 null undefined
避免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)
}
}
小結(jié): 真值窄化幫助我們更好的處理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是檢查對象中是否有屬性,現(xiàn)在充當(dāng)了一個 "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表達式的右側(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
}
// 報錯
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 | 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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Bootstrap模態(tài)框(modal)垂直居中的實例代碼
這篇文章主要介紹了Bootstrap模態(tài)框(modal)垂直居中的實例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-08-08
uni-app小程序中父組件和子組件傳值的實現(xiàn)實例
uniapp父子組件引用傳值,和vue的一樣,沒有小程序那樣的麻煩,下面這篇文章主要給大家介紹了關(guān)于uni-app小程序中父組件和子組件傳值的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-08-08
javascript讀寫XML實現(xiàn)廣告輪換(兼容IE、FF)
最近更新網(wǎng)站首頁廣告,ASP.NET的廣告控件很容易實現(xiàn)這點,可首頁是靜態(tài)頁面,聯(lián)想廣告控件的原理決定采用javascript+xml實現(xiàn)這點方面配置,更新廣告時只要更新xml即可,方便了廣告輪換2013-08-08
TensorFlow.js 微信小程序插件開始支持模型緩存的方法
這篇文章主要介紹了TensorFlow.js 微信小程序插件開始支持模型緩存的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02

