番禺网站开发哪家好,呼和浩特做网站的公司有哪些,网站免费建站o,徐州网站开发培训目录
一、为什么什么是TypeScript#xff1f;
1、发展历史
2、typescript与javascript
3、静态类型的好处
二、基础语法
1、基础数据类型
2、补充类型
3、泛型
4、泛型的高级语法
5、类型别名类型断言
6、字符串/数字 字面量
三、高级类型
1、联合/交叉类型…目录
一、为什么什么是TypeScript
1、发展历史
2、typescript与javascript
3、静态类型的好处
二、基础语法
1、基础数据类型
2、补充类型
3、泛型
4、泛型的高级语法
5、类型别名类型断言
6、字符串/数字 字面量
三、高级类型
1、联合/交叉类型
2、类型保护与类型守卫
3、merge函数
4、函数返回值类型
四、工程应用
1、浏览器Web--webpack
2、NodeJs
五、学习总结
实例当函数及传入的参数可能为任意类型时 一、为什么什么是TypeScript
1、发展历史
2012-10:微软发布了TypeScript第一个版本0.8) 2014-10: Angular 发布了基于TypeScript的2.0版本 2015-04:微软发布了 Visual Studio Code 2016-05: types/react 发布TypeScript可开发React 2020-09:Vue发布了3.0版本官方支持 TypeScript 2021-11:v4.5版本发布
2、typescript与javascript
1typescript静态弱类型的语言
2javascript动态弱类型的语言
3动态、静态类型 ①动态类型是在执行阶段才确定类型的匹配 javascript是脚本语言代码可以直接贴到浏览器的控制台执行执行过程中浏览器js解析引擎才会进行类型的匹配当输入类型错误时报错即动态类型的一个特征是在运行是才进行类型的检验/匹配 ②静态类型会提前进行类型的检验/匹配
4强、弱类型 ①弱类型当字符串1和数字1相加时js在执行时会进行隐式类型转换 ②强类型字符串1和数字1不能相加
3、静态类型的好处
1可读性增强基于ts的语法解析TSDocide可以得到增强 当写完一段代码函数/对象过一段时间就容易遗忘难以整理成文档时 ①TSDoc语法解析可以自动生成文档同时类型也会被说明含义也就是在写类型时相当于在写文档节约解读代码所花费的时间 ②ide有很强的类型提示
2可维护性增强:在编译阶段暴露大部分错误 编译暴露的问题语法拼写错误类型匹配错误当把字符串传给函数但是函数需要的是对象等等 基于上面两点使用typescript在多人合作的大型项目中能获得更好的稳定性和开发效率
3ts是js的超集 ①包含于兼容所有js特性支持共存 ②支持渐进式引入与升级
二、基础语法
1、基础数据类型
1常见的基础数据
/*ts*/
/*字符串*/
const q: string string ;
/*数字*/
const w: number 1;
/*布尔值*/
const e: boolean true;
/* null */
const r: null null;
/* undefined */
const t: undefined undefined;/*js*/
/*字符串*/
var q string;
/*数字*/
var w 1;
/*布尔值*/
var e true;
/* null */
var r null;
/* undefined */
var t undefined;2对象类型 自定义对象类型
const bytedancer: IBytedancer {jobId: 9303245,name: Lin,sex: man,age: 28,hobby: swimming,
}
interface IBytedancer {/*只读属性:约束属性不可在对象初始化外赋值*/readonly jobId: number;name: string;sex: man | woman | other;age: number;/*可选属性:定义该属性可以不存在*/hobby?: string;/*任意属性:约束所有对象属性都必须是该属性的子类型*/[key: string]: any;
}
/*报错:无法分配到jobId因为它是只读属性*/
bytedancer.jobId 12345;
/*成功:任意属性标注下可以添加任意属性*/
bytedancer.plateform data;
/*报错:缺少属性“name, hobby可缺省*/
const bytedancer2: IBytedancer {jobId: 89757,sex: woman,age: 18,
}3函数类型
function add(x,y){return x y;
}
const mult (x,y) x*y;①直接在函数上进行类型的补充
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;4函数重载
/*对getDate函数进行重载timestamp为可缺省参数*/
function getDate(type: string , timestamp?: string): string; interface IGetDate {(type: string, timestamp?: string): string;(type: date, timestamp?: string): Date;(type: string | date, timestamp?: string): Date | string;
}
/*不能将类型(type: any,timestamp: any) string | Date分配给类型IGetDate
不能将类型string | Date”分配给类型“string”
不能将类型Date”分配给类型string*/
const getDate2: IGetDate (type, timestamp) {const date new Date(timestamp);return type string ? date.toLocaleString() : date;
}5数组类型
/*「类型方括号」表示*/
type IArr1 number[];
/*泛型表示*/
type IArr2 Arraystring | number | Recordstring, 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, {}, []];
2、补充类型
/*空类型表示无赋值*/
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 Arraynumber;
3、泛型
1场景1 ①设置一个数组可以传入任意类型希望传入数字时输出数字的Array传入字符串时输出字符串的Array不然会组成数据丢失的情况因为会被重写成any达不到效果 ②那么就需要泛型可以不预先指定数据的类型在数据使用的时候根据内容才确定其类型
function getRepeatArr(target) {return new Array(100).fill(target);
}
type IGetRepeatArr (target: any) any[];
/*不预先指定具体的类型而在使用的时候再指定类型的一种特性*/
type IGetRepeatArrR T(target: T) T[];2其它场景 泛型其实就是一种变量指代
/*泛型接口多泛型*/
interface IXT, U {key: T;val: U;
}
/*泛型类*/
class IManT{instance: T;
}
/*泛型别名*/
type ITypeArrT ArrayT;3注意定义区别 ①函数在函数定义的()前使用中的内容就是泛型 ②类/别名/接口都是在该类型别名后使用中的内容就是泛型
4、泛型的高级语法
1泛型约束 泛型需要限制在一定范围内如它可以是传入的时候被使用但是必须有一个限定 2泛型参数默认类型
/*泛型约束:限制泛型必须符合字符串*/
// extends表示类型约束
type IGetRepeatStringArr T extends string(target: T) T[];
const getStrArr: IGetRepeatStringArr target new Array(100).fill(target);
/*报错:类型“number”的参数不能赋给类型“string的参数*/
getStrArr(123);/*泛型参数默认类型*/
type IGetRepeatArrT number (target: T) T[];
const getRepeatArr: IGetRepeatArr target new Array(100).fill(target);
/*报错:类型“string”的参数不能赋给类型“number的参数*/
getRepeatArr( 123);
两种区别上面是函数泛型下面是类型别名的泛型
5、类型别名类型断言
/*通过type关键字定义了I0bjArr的别名类型*/
// 用一个变量承载比较复杂的类型
type IObjArr Array{key: string;[objKey: string]: any;
}
// keyBy函数将arr转换成object
// reduce()函数给result传入一个空obj因为result的类型没有被指定ts会进行默认类型推断
function keyByT extends IObjArr(objArr: ArrayT) {/*未指定类型时, result类型为f}*/const result objArr.reduce((res, val, key) {res[key] val;return res;}, {});/* 通过as关键字断言result类型为正确类型*/return result as Recordstring, T;
}
6、字符串/数字 字面量
/*允许指定字符串/数字必须的固定值*/
/* IDomTag必须为html、body、div、span中的其一*/
type IDomTag html | body | div | span ;
/* IOddNumber必须为1、3、5、7、9中的其一*/
type IOddNumber 1 | 3 | 5 | 7 | 9;三、高级类型
1、联合/交叉类型
1原始写法
// 为书籍列表编写类型
const bookList [{author: xiaoming,type: history,range: 2001-2021,
}, {author: xiaoli,type: story,theme: love,
}]
// 类型声明繁琐存在较多重复
interface IHistoryBook {author: string;type: string;range: string
}
interface IStoryBook {author: string;type: string;theme: string
}
type IBookList ArrayIHistoryBook | IStoryBook;2联合交叉类型法 ①联合类型IA|IB;联合类型表示一个值可以是几种类型之一 ②交叉类型IA IB;多种类型叠加到一起成为一种类型它包含了所需的所有类型的特性
type IBookList Array{author: string;
} ({type: history;range: string;
} | {type: story;theme: string;
})2、类型保护与类型守卫
1原始写法
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);}
}2类型守卫 ①额外定义了getIsIA()函数可以接收一个参数【IA或IB】 ②判断时写新语法类型谓词is判断是否是IA ③返回时使用断言as当存在a时断言一定是IA
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;
}
function log2(arg: IA | IB) {if (getIsIA(arg)) {console.log(arg.a1)} else {console.log(arg.b1);}
}3typeof、instance类型保护 reverse()只有数组才支持字符串不支持要先把字符串转为数组
//实现函数reverse
//其可将数组或字符串进行反转
function reverse(target: string | Arrayany) {/* typeof类型保护*/if (typeof target string) {return target.split().reverse().join();}/* instance类型保护*/if (target instanceof Object) {return target.reverse();}
}
4总结 ①当两个类型完全没有任何交集时才需要写类型守卫 ②回到前面书籍数据的例子
//实现函数logBook类型
//函数接受书本类型并logger出相关特征
function logBook(book: IBookItem) {//联合类型类型保护自动类型推断if (book.type history) {console.log(book.range)} else {console.log(book.theme);}
}3、merge函数
1传统类型定义
/**
*merge函数类型实现合并sourceObj、targetObj
*要求sourceObj必须为targetObj的子集
*/
// 方法一
function merge1(sourceObj, targetObj) {const result { ...sourceObj };for (let key in targetObj) {const itemVal sourceObj[key];itemVal (result[key] itemVal);}return result;
}
// 方法二
function merge2(sourceObj, targetObj) {return { ...sourceObj, ...targetObj };
}interface ISourceObj {x?: string;y?: string;
}
interface ITargetObj {x: string;y: string
}
type IMerge (sourceObj: ISourceObj, targetObj: ITargetObj) ITargetObj;
/**
*类型实现繁琐:若obj类型较为复杂则声明source和target便需要大量重复2遍
*容易出错:若target增加/减少key则需要source联动去除
*/2使用泛型 ①IMerge对象
extends类型约束Record高级类型Recordstring, any泛型分别表示指定object中key和value的类型即object的any类型的简单表达对T泛型做限定必须是object类型targetObj就是一个T返回的也是TIPartial通过传入任意类型后得到其子集
注意函数的泛型定义是在()前面定义的类型泛型定义是在类型后面定义的
②IPartial
keyof相当于取值对象中的所有key组成的字符串字面量, 如type IKeys keyof { a: string; b: number }; // type lKeys a | bin相当于取值字符串字面量中的一种可能配合泛型P, 即表示每个key?通过设定对象可选选项即可自动推导出子集类型IPartial通过泛型要求传入的必须是对象然后通过keyof取出所有的key
interface IMerge {T extends Recordstring, any(sourceObj: PartialT, targetObj: T): T;
}
type IPartialT extends Recordstring, any {[P in keyof T]?: T[P];
}4、函数返回值类型
1对函数类型的定义就是对函数的入参出参定义 下面的delayCall函数例子中入参是一个函数而出参是一个Promise函数返回值
//实现函数delayCall的类型声明
//delayCall接受一个函数作为入参,其实现延迟1s运行函数
//其返回promise结果为入参函数的返回结果
function delayCall(func) {return new Promise(resolve {setTimeout(() {const result func(); resolve(result);}, 1000);});
}type IDelayCall T extends () any(func: T) ReturnTypeT;
type IReturnTypeT extends (...args: any) any T extends (...args: any) infer R ? R : any
//关键字【extends】跟随泛型定义出现时表示类型推断其表达可类比三元表达式
//如T判断类型?类型A:类型B
//关键字【infer】出现在类型推荐中表示定义类型变量可以用于指代类型
//如该场景下将函数的返回值类型作为变量使用新泛型R表示使用在类型推荐命中的结果中
四、工程应用
1、浏览器Web--webpack
1配置webapack loader相关配置 webapack loader将webpack中不能识别的文件转换成webpack可以识别的文件 2配置tsconfig.js文件 3运行webpack启动/打包 4loader处理ts文件时,会进行编译与类型检查
2、NodeJs
1使用TSC进行编译将ts文件转换成js文件 2过程 ①安装Node与npm ②配置tsconfig.js立件 ③使用npm安装tsc ④使用tsc运行编译得到js文件
五、学习总结
通过本次学习对ts的泛型有了更清晰明确的认识
实例当函数及传入的参数可能为任意类型时
1普通写法 给函数及传入的参数定义any类型
function identity(msg:any):any{return msg;
}由于算法的复用会导致这个函数可以接收任何类型的msg参数这样就丢失了一些信息传入的类型与返回的类型应该是相同的
2泛型写法 给函数添加泛型类型变量TT能够捕获用户传入的类型然后使用这个类型 实现在函数执行时才去获取类型
function identityT(msg:T):T{return msg;
}“精辟总结”普通函数要求我们对值编程泛型则要求我们对类型编程