TypeScript | 青训营笔记
** 这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天 **
一、为什么是TypeScript
- Js 是动态类型 弱类型语言
- Ts是静态类型 弱类型语言
动态类型:程序执行的时侯才会进行类型的匹配 静态类型:编译时进行类型的匹配(可读性增强,可维护性增强,多人合作的大型项目中,获得更好的稳定性和开发效率)
弱类型语言:不同类型变量进行运算时会进行隐形类型转换
二、基本语法
1.基本数据类型
在变量后使用冒号+类型(string,number,boolean,null,undefined)的方式来定义变量类型 如
const q:string = 'string'
2.对象数据类型
使用interface(接口)来定义一个类型 一般的情况下,我们使用大写的I来约定一个类型 如
interface IBytedancer{
readonly jobId:number;//只读属性,属性不可以在对象初始化外赋值
name:string;
sex:'man'|'woman';
hobby?:string;//可选属性,定义该属性可以不存在
[key:string]:any;//任意属性,约束所有对象属性都必须是该属性的子类型
}
3.函数类型
为函数声明类型有两种方式
function add(x,y){
return x + y;
}
const mult = (x,y)=> x*y;
1.给函数对象赋值一个类型的声明
interface IMult{
(x:number,y:number):number;
}
const mult:IMult = (x,y)=>x*y;
2.直接在函数上进行声明
function add(x:number,y:number):number{
return x+y;
}
function mult:(x:number,y:number)=> number = (x,y)=> x*y;
4.数组类型
type IArr1 = number[];//类型+方括号表示
type IArr2 = Array<string | number | Record<string,number>>//泛型表示
type IArr3 = [number,number,string,string] //元组表示
interface IArr4{
[key:number]:any;
}//接口表示
三、TS泛型
不预先指定具体的类型,而在使用的时候再指定类型的一种特性
type IGetRepeatArrR = <T>(target:T) => T[]
1.接口泛型 & 多泛型
interface IX<T,U>{
key:T;
val:U;
}
2.泛型类
class IMan<T>{
instance:T;
}
3.泛型别名
type ITypeArr<T> = Array<T>;
4.泛型约束
限定泛型必须符合定义的类型
type IGetRepeatStringArr = <T extends string>(target:T) => T[];
5.泛型默认类型
type IGetRepeatArr<T = number> = (target:T) => T[];
断言
当TS自动推断的类型不符合我们的期望,并且我们知道该变量一定符合某种类型时可以使用断言 result as Record<string,T>;
四、高级类型
1.联合类型/交叉类型
场景:为书籍列表编写类型 -> 类型声明繁琐,存在较多重复
const bookList = [{
author:'xiaoming',
type:'history',
range:'2001-2021',
},{
author:'xiaoli',
type:'story',
theme:'love',
}]
interface IHistyorBook {
author:string;
type:string;
range:string;
}
interface IStoryBook {
author:string;
type:string;
theme:string;
}
type IBookList = Array<IHistoryBook | IStoryBook>;
如何改进?
- 联合类型:A|B
- 交叉类型:A&B
type IBookList = Array<{
author:string;
} & ({
type:'history';
range:string;
}|{
type:'story';
theme:string;
})>
2.类型保护与类型守卫
interface IA{a:1,a1:2}
interface IB{b:1,b1:2}
function log(arg:IA | IB){
//报错:类型‘IA|IB ’上不存在属性‘a’。类型‘IB’上不存在属性‘a’
//结论:访问联合类型时,出于程序安全,仅能访问联合类型中的交集部分
if(arg.a){
console.log(arg.a1)
}else{
console.log(arg.b1)
}
}
如何改进代码? answer:可以通过类型首位的方法
interface IA{a:1,a1:2}
interface IB{b:1,b1:2}
//类型守卫:定义一个函数,它的返回值是一个类型谓词,生效范围为子作用域
function getIsIA(arg:IA|IB):arg is IA{//类型谓词
return !!(arg as IA).a; //两次取反的目的是为了让null 转换成true true再转换成false,从而实现null->false的转换
}
function log2(arg:IA | IB){
if(getIsIA(arg)){
console.log(arg.a1)
}else{
console.log(arg.b1)
}
}