TypeScript | 青训营笔记

47 阅读3分钟

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)
	}
}