这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
TypeScript
一、为什么使用TypeScript
ts能让前端库项目开发变的更简单。
使用js编程的时候,有一种让人很纠结的情况,就是程序运行错误是上层传入参数错误导致的,不管是直接还是间接。
使用传统js写库,对这种情况其实是很纠结的。我们都希望库的导出接口能健壮一些,错误信息明确一些,那怎么办呢?要么本来可以返回void的接口,凭空多出了返回值,要么就抛异常。我个人觉得抛异常更合理,你总不能为了排错方便,就劣化本来设计的很好的接口签名。但是这一点也有争议,我同事专门批评过我这一点,他的看法是底层代码尽量不要抛异常,因为测试用例可能覆盖不到你抛异常的情况,导致线上隐患。
总而言之吧,你如果不希望错误参数传染到你内部的逻辑流程,你在接口里就要写一大堆检查代码,如果让程序员自己写,就会五花八门,如果使用系统性解决方案,比如JOI,工作量说实话也不小,性能也不会很好。而且最终还是解决不了我同事说的那个问题——运行时报错很难被测试用例完全覆盖,还是会导致线上隐患。
二、TypeScript基本类型
1、字符串类型
var text:string = 'hello world';
console.log('字符串:',text);
2、数字类型
var number:number = 1;
console.log("数字:",number);
3、布尔类型
var bool:boolean = false;
console.log("布尔:",bool);
4、数组类型
// 1-数字数组
var array:number[] = [1,2,3];
console.log("数组1:",array);
要注意:function test() {console.log(arguments);}中arguments在typescript中默认为数字数组,但是却不能使用数字数组的方法
// 2-泛型
var arr:Array<number> = [1,2,3]
console.log("数组2:",arr);
// 3-元组tuple
var arrays:[string,number] = ['hello',6];
console.log("元组:",arrays);
// 4-不确定类型数组
var arraylist: any[] = ['hello','world',123] ;
console.log('不确定数组:',arraylist);
5、any类型
不建议使用,因为any类型ts无法审查错误
var notsure:any = 'handsome';
console.log('any:',notsure);
6、unitype 联合类型
var numberOrString:number|string|boolean = 123;
numberOrString = '123';
numberOrString = false;
注意:联合类型中右侧值只能为左侧列举出的类型,否则会引起报错
7、interface接口类型
interface Person {
name:string;
age:number;
gender?:string;
// 加问号表示可选属性
readonly id: number;
// readonly的值不能重新赋值,与const差不多
}
readonly 和 const 用法差不多,只不过readonly只能使用在interface中,const只能使用在函数中
如果定义一个类kb,类型为Person,那么kb中需要包含Person中所有必选属性
let Kb: Person = {
name: 'kb',
age: 19,
id: 1
}
8、类型别名
可以用type定义变量为一个类型的别名,可以使代码更清晰,可读性更高,例如下面声明PlusType为sum这一类的类型别名
type PlusType = (x:number,y:number) => number
function sum(x:number,y:number) :number {
return x+y;
}
const sum2 :PlusType = sum;
9、generics泛型
泛型是指在声明时不指定变量类型,使用时才进行定义的变量类型
下面例子的echo函数就使用了泛型,echo括号中的值可以为任意类型,但是echoWithArray()函数中调用了arg的length方法,所以只有数组和字符串类型可以被添加进去。
function echo<T>(e: T) :T {
return e;
}
const result = echo('string');
function echoWithArray<T>(arg:T[]) :T[] {
console.log(arg.length);
return arg;
}
可以使用约束泛型,使echoWithArray()函数的复用性增强
interface IWithLength {
length:number;
}
function echoWithLength<T extends IWithLength>(arg:T) :T {
console.log(arg.length);
return arg;
}
通过继承的方式,使泛型继承了IWithLength的length方法,这样,不仅只有array和string类型可以被填入,其他类型的数据也会因有length方法而合法
10、partial类型
partial可以说很好的解决了interface的实例中,每一次修改都要包含所有内容的问题,虽然不用partial也可以解决(将所有内容前都打上'?'),但显然不如partial方便
interface Blog {
id: string;
title: string;
slug: string;
categories: string[];
tags: string[];
featureImageUrl?: string;
content: string;
}
const draft: Partial<Blog> = { title: 'title' }