本次一共推出三篇文章,TS基础篇、TS高阶篇、TS习题篇,三篇文章均已发布。
语法篇
1. 联合类型的问题
interface a1{kind:'circle' | 'square'rad?:numberside?:number
}function getAre(a:a1){// return a.rad*3 //此处报错,因为 rad 为可选参数,可能未定义return a.rad!*3 //加上 ! 解决该问题,表示类型推断排除null、undefined,// 即只有类型推断不为null、undefined,我们才进行后面的步骤
}// 上面虽然解决了这个问题,但是解决方法有点不太恰当,因为参数a可能是未传参数,
// 这在ts中虽然不会引起错误,但在js中可能会引起报错// 最好的解决方法是分别定义数据类型
// 如下所示
// interface Circle {
// kind: 'circle'
// radius: number
// }// interface Square {
// kind: 'square'
// sideLength: number
// }// type Shape = Circle | Square // function getArea(shape: Shape) {
// switch(shape.kind) {
// case 'circle':
// return Math.PI * shape.radius ** 2// case 'square':
// return shape.sideLength ** 2
// }
// }// TS中的!和?用法// 1. 属性或参数中使用 ?:表示该属性或参数为可选项// 2. 属性或参数中使用 !:表示强制解析(告诉typescript编译器,这里一定有值),常用于vue-decorator中的@Prop// 3. 变量后使用 !:表示类型推断排除null、undefined
2. 类型守卫
所谓类型守卫,就是当一个变量或参数同时具有多种类型时,但我们只想针对于其中某一种类型进行运算
例如使用 typeof 来判断数据类型,即可实现在特定类型做特定运算
2.1. typeof 关键字
function print(str: number | string[] |null){if(typeof str === 'string'){// 当类型为 string 时进行相应运算}else if(typeof str === 'object'){// 当类型为 object 时进行相应运算// 但此处要注意,null的类型也为object,如果想避免 null 可加上 && 运算符// 即 (str && typeof str === 'object') 因为 null 在if判断后为false,故可直接写入// 当然,如果不嫌麻烦 (str !== null && typeof str === 'object'),这样也是可以的}else{}
}
2.2. 真值缩小
// 我们需要知道,下面这些值在 if() 中,结果必定为false,反之为true
// {
// 0
// NaN
// "" (空字符串)
// 0n (bigint零的版本)
// null
// undefined
// }function demo13(x: number | undefined){if(!x){return x}else{console.log(x+1)}
}
demo13(3)
demo13(undefined)// 上面,我们使用 !取反,如果为 undefined 就 return,否则输出x+1
2.3. 等值缩小
function demo14(x:string | number, y: string | boolean){if(x===y){// 此处的if判断很巧妙,因为两个参数身上都有共同的一个属性 string// 所以只有当两者都为 string 类型时才有可能相等,故可以在此处调用 string 身上的方法x.toUpperCase()y.toLocaleLowerCase()}
}function demo15(x:null | number | undefined){if(x != null){console.log(x+1)}// 这里需要注意:我们虽然只做了 x != null 这一个判断,也就是说 x 还有可能为undefined// 那为什么我们在下面进行加法运算,这里不会报错?这是因为我们用的是 != 即宽松的不等于判断,// 这个宽松的不等于判断可以同时排除 null 和 undefined 两个值// 但是如果用的是 x !== null ,这样就只能排除 null 一个值
}
demo15(1)
demo15(undefined)
2.4. in操作符类型缩小
type a={swim:()=>void
}type b={fly:()=>void
}
type c={swim?:()=>void, //加上 ? 表示该参数为可选参数fly:()=>void
}
function demo16(x:a|b){if('swim' in x){return x.swim()}// 这个in操作符的作用就是判断值是否在某个东西身上,是则返回true,否则为false// 所以上面代码表示为:'swim' 是否在 x 身上,如果在,那x必定为 type所定义的类型 a// 故可以调用 swim()方法
}function demo17(x:a|b|c){if('swim' in x){// return x.swim() 报错// 因为加入了类型 c,且类型c身上是有 swim() 方法的,这样本身是没问题的// 但是c身上的 swim() 方法是可选的,也就是说可能为空,所以说会报错return (x as a).swim()// 我们加上类型断言便可解决这个问题,即只有当 x 类型为 a 时,才会去调用 swim() 方法}
}
2.5. instance操作符缩小
function demo18(x: Date | string){if(x instanceof Date){// 判断 x 是否存在 Date 这么一个方法console.log('123')}else{console.log(x.toLocaleUpperCase())}
}demo18(new Date())
demo18('hello')
2.6. 分配缩小
let x3=Math.random() < 0.5 ? 10 : 'hello'
x3=1
console.log(x3)
x3='dd'
console.log(x3)
// x3=true //报错,因为变量x3并不具有 bool 类型// 分配类型缩小和 let x3:string | number 类似,只是他不是
// 直接告诉变量他所拥有的类型,而是通过判断来给变量进行赋值
// 这样通过类型推断,从而获取拥有到数据类型.// 这里需要注意的是,仅管我们是通过判断来给变量进行赋值,但是
// 我们也可以拥有所有的变量类型
2.7. 控制流分析
function demo19(){let x:string | number | booleanx=Math.random() < 0.5console.log(x)if(Math.random()<0.5){x='hello' //把类型限制为 stringconsole.log(x)}else{x=100 //把类型限制为 numberconsole.log(x)}// 通过上面的操作,成功将返回值 x 类型限制为 string | numberreturn x// 这里需要注意了,这里虽然是判断,也就是说只会有一种类型成立,// 但是我们是可以同时拥有这两种数据类型的,和上一节分配缩小是一样的
}let x4=demo19()
x4='hello'
x4=100
// x4=true //报错
2.8. 类型谓词
type Fish={name:stringswim:()=>void
}type Bird={name:stringfly:()=>void
}
// 类型谓词是用来限制返回值的数据类型
// 类型谓词书写格式:参数 is 类型
// is是固定不变的,is左侧必须为函数本身所使用的一个参数
// is右侧必须为一个数据类型
function demo20( pet: Fish | Bird):pet is Fish{// return true //返回值为 true 则为 Fish 数据类型// return false //返回值为 false 则为 Bird 数据类型return (pet as Fish).swim !== undefined// 易错点:这里我们很容易就写成 pet.swim !== undefined 这是不对的// 因为 pet 可能为 Bird 数据类型,而Bird数据类型没有 swim 这个方法,ts便会提示报错// 我们需要加一个类型断言 (pet as Fish) 即代表只有当 pet 数据类型为Fish时,我们才进行接下来的操作
}
3. 类型断言
TypeScript 的类型断言(Type Assertions)是开发者向编译器表明某个值的特定类型的一种方式。类型断言允许你更具体地说明某个值的类型,而不必等待编译器的自动推断。类型断言不会在运行时产生任何影响,仅用于编译阶段的类型检查
3.1. 语法
TypeScript 提供了两种类型断言的语法:
- 尖括号语法(Angle-bracket syntax)
as
语法
// 尖括号语法类似于在值的前面加上类型
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).len