Typescript入门 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第十三天。今天的课堂内容讲的是typescript的入门,感觉收获颇丰。以前稍微写过一点typescript,但是也就只是用到了ts的类型而已,距离如何正确且优雅的使用ts还相距甚远,今天林皇老师的课《Typescript入门》让我觉得干活满满。特此记录下笔记,帮助自己学习ts。
Typescript发展史
从2012年10月微软发布TypeScript第一个版本至今已有十年时间,这期间Angular、React、Vue三大主流的前端框架都相继支持TypeScript。甚至连vue3的底层都使用TS进行编写,可见TypeScript正在逐渐成为主流。
为什么要使用TypeScript
Typescript其实是源于JavaScript
- JavaScript
- 动态类型:运行阶段才能够确定一个变量的类型,变量的类型可以随时发生变化
- 弱类型:能进行隐式类型装换,比如c语言运行
1+"1"就会报错,而js运行1+"1"会得到"11"
- TypeScript
- 静态类型:申明变量时就确定了变量的类型,变量的类型不可以发生改变。
- 弱类型:能进行隐式类型装换,比如c语言运行
1+"1"就会报错,而Ts运行1+"1"会得到"11"
而静态类型的TS相较于动态类型的JS会有哪些优点呢?
使用好TS,能帮助我们增强项目的可读性和可维护性。帮助我们更优雅的编写代码。
基础语法
基本数据类型
在变量名后面加上:变量类型来定义变量的类型
对象数据类型
使用interface(接口)来定义对象类型。
- readonly:表示只读属性,表示属性不可以在对象初始化之外进行赋值
- ?:可选属性,表示属性可以存在也可以不存在
sex:"man" | "woman" | "other":表示取值只能为man、woman、other中的一个any:是ts特有的一个类型,表示所有类型,任何类型。
函数类型
我们用js编写函数时一般这样写
function add(x,y){
return x+y
}
const mult = (x,y)=>x*y
而用ts编写函数时,可以给形参和函数返回值加上类型
function add(x:number,y:number):number{
return x+y
}
const mult:(x:number,y:number)=>number = (x,y)=>x*y
如果嫌在函数参数比较多,在参数上写类型会让整个代码很长,不好看,我们可以这样写
interface IMult{
(x:number,y:number):number
}
const mult:IMult = (x,y)=>x*y
数组类型
/*「类型+方括号」表示*/
type IArr1 = number[];
/*泛型表示*/
type IArr2 = Array<string | number | Record<string,number>>;
/*元祖表示*/
type IArr3 = [number,number, string,string] ;
/*接口表示*/
interface IArr4 {[key: number] : any;}
const arr1: IArr1 = [1,2,3,4,5,6];
const arr2: IArr2 = [1,2,'3','4', { a: 1 }];const arr3: IArr3 = [1,2,'3','4'];
const arr4 : IArr4 = [ 'string' ,() => null,{},[]];
补充类型
/*空类型,表示无赋值*/
type IEmptyFunction = () => void;
/*任意类型,是所有类型的子类型*/
type IAnyType = any;
/*枚举类型:支持枚举值到枚举名的正、反向映射*/
enum EnumExample {
add = '+',
mult = '*',
}
EnumExample[' add '] == '+'; EnumExample['+'] = 'add ';
enum ECorlor { Mon, Tue, Wed, Thu, Fri, Sat, Sun }; ECorlor['Mon'] == 0;
ECorlor[0] == 'Mon ';/*泛型*/
type INumArr = Array<number>;
泛型
作为一个“javaboy”,泛型在TS里的出现真的让我感到太舒服了。
/*泛型接口&多泛型*/
interface IX<T, U> {
key: T;
val: U;
}
/*泛型类*/
class IMan<T> { instance: T; }
/*泛型别名*/
type ITypeArr<T> = Array<T>;
当我们有一个函数
function getRepeatArr(target) {
return new Array(100).fill(target);
}
我们想使用ts来限制传入的参数的类型和输出的数组类型一致,简单粗暴的写法可以这样写
type IGetRepeatArr = (target: any) => any[];
const getRepeatArr2:IGetRepeatArr = (target)=>new Array(100).fill(target);
但实际上这样简单粗暴的方式是达不到我们想要的效果的,我们需要传入的参数是number类型,那返回的是number的数组,但是上面这种简单粗暴的写法,传入的number类型却有可能返回的是string数组。因为any类型的意思是任意类型。
我们利用泛型可以这样写
/*不预先指定具体的类型,而在使用的时候再指定类型的一种特性*/
type IGetRepeatArrR = <T>(target: T) => T[];
const getRepeatArr2:IGetRepeatArrR = (target)=>new Array(100).fill(target);
通过泛型,不预先指定类型,而是在使用的时候再指定类型,来做到输入与输出的类型一致。
泛型约束
使用泛型的时候,可以使用泛型约束来将泛型限制在一定范围内。 使用extends关键字,限制泛型的类型。如下代码,限制泛型只能是string类型,则getSetArr方法使用IGetRepeatStringArr类型时,输入值只能为string,输入number就会报错
/*泛型约束:限制泛型必须符合字符串*/
type IGetRepeatStringArr = <T extends string>(target: T) => T[];
const getStrArr: IGetRepeatStringArr = target => new Array(100).fill(target);
/*报错:类型"number"的参数不能赋给类型"string”的参数*/
getStrArr(123);
泛型参数默认类型
泛型可以使用=来设置默认的类型
当getRepeatArr方法使用IGetRepeatArr类型时,没有设置泛型,则泛型默认为number,传入String类型的参数就会报错
/*泛型参数默认类型*/
type IGetRepeatArr<T = number> = (target: T) => T[];
const getRepeatArr: IGetRepeatArr = target => new Array(100).fill(target);
/*报错:类型"string"的参数不能赋给类型“number"的参数*/
getRepeatArr('123')
当传入一个泛型后,默认类型被覆盖,报错就消失了
/*泛型参数默认类型*/
type IGetRepeatArr<T = number> = (target: T) => T[];
const getRepeatArr: IGetRepeatArr<string> = target => new Array(100).fill(target);
/*报错:类型"string"的参数不能赋给类型“number"的参数*/
getRepeatArr('123');