TypeScript编程
一、TypeScript概念
TypeScript是JavaScript超集,完全遵循javaScript中ES5\ES6+的规范。
TypeScript强类型编程方式,可以对我们代码进行类型约束。
在你写代码的时候,需要约束类型、约束函数、约束组件之间参数传递等等
TypeScript微软发布出来,在学习TypeScript过程中实际上就是学习约束,不会在重复学习JS相关概念
强类型编程语言:定义变量的时候,必须明确规定数据类型,否则无法通过代码编译
JavaScript若类型语言:定义变量的时候,无需声明数据类型,变量数据类型由值来决定的。
js
js:
var m = 20 //m的数据类型在写代码的时候无法确认,只有运行这段代码,内存根据20这个值决定m类型number
m = "xiaowang" //代码运行过程m类型变成string
js
ts:
var m:number = 20 //m类型number,内存开启8个字节
m = "xiaowang" //代码报错,m确认了数据类型后,无法接受其他值
js
java:
int m = 20 //int短整型整数,内存4个字节存放20
long m2 = 100 //长整型整数,内存8个字节存放100
强类型语言一般都要经过过程;
比如你们写的java代码
js
int age = 23
写完了保存代码,java环境编译这段代码,将我们java代码编译为字节码,机器能识别语言,虚拟机将字节码解释成机器语言。
弱类型语言JS无需编译:
js
var k = 20
直接将这段代码拿到浏览器运行,一行一行的解释代码,让浏览器运行二进制代码。
问题:
- 你们写的JS代码,在编写过程中不是代码语法写错了,无法提示你错误信息。必须运行过程中浏览器检测出异常代码。抛出错误。
TypeScript:在JS基础上做了类型约束,编写的TS代码需要经过编译,生成JS代码,在拿去运行。将TS编译为JS代码。一旦编译过程发现错误,立马提示出来。
js
let obj = {id:1}
obj.name = "xiaowang"
二、环境搭建
(1)安装ts的环境
js
npm install typescript -g
tsc -v //查看版本号
(2)写一段ts代码运行
js
let address:string = "武侯区"
console.log(address);
address = "高新区"
跟JS代码比较,在定义数据的时候,多了约束类型,数据类型。
(3)编译代码
将ts代码编译为js代码,才能在浏览器运行。
浏览器无法直接运行ts代码的。浏览器智能js、html、css
编译代码
js
tsc index01.ts
默认在同级目录下面创建一个index01.js文件。
(4)自动编译
当检测到ts代码产生变化了,默认自己开始将ts代码编译为js代码
在指定的项目下面执行,将这个普通项目初始化ts项目
js
tsc --init
在项目中产生一个tsconfig.json文件。这个文件里面存放项目编译的时候配置规则。
你们可以打开的配置,编译的代码默认放在同级目录的js文件夹里面。如果没有创建一个
js
"outDir": "./js",
终端--->运行任务-->typescript-->监视tsconfig.json
在终端开启一个监视任务,ts代码发生任何变化,理解监视代码,并编译为js代码
前期学习的时候,我们是自己搭建ts项目。
后期学习在vue框架、react框架里面使用ts
三、数据类型介绍
基本类型的数据
number、string、boolean、undefined、null
js
let m:number = 10
let name:string = "xiaowang"
let bool:boolean = true
关于数据类型一旦约束了,那就无法在修改。数据类型在内存表示内存空间大小。
js
//联合类型,多种类型同时存在
let m:number | undefined | null
m = null
if(m){
}
undefine和null一般不会单独使用,一般作为联合类型一起使用。给变量一个特殊的结果
引用类型
数组类型
数组、对象、
数组类型的定义:数组进行约束,指定这个数组里面存放的数据类型
js
let array:number[] = [1,2]
let temp:string[] = ["xiaowang","1"]
let array2:boolean[] = []
array2.push(true)
默认要求数组里面只能存放同一种数据类型。
js
//users是Array类型,存放的number类型数据
let users:Array<number> = [1,2,3]
元组类型
元组类型是一种特殊的数组,专门提出的一种数据类型。允许你数组中存放不同的数据类型,必须指定每一个位置什么类型。
js
let students: [number, string, boolean] = [1, "xiaowang", true]
对象类型
js
let obj:object = {}
let obj2:object = {id:1}
console.log(obj2.id);
let array3:object = [1,2,3]
let fun:object = function(){
}
object可以表示对象类型,泛指,很多类型都支持,数字、object对象、函数也都支持。
无法明确表示出具体那种对象。
js
obj2.id //编译报错
如果针对Object类型对象,指定数据类型
js
let classes:{id:number,name:string} = {id:1,name:"xiaofei"}
复杂类型的数据,要求约定出每一个属性的类型是什么
js
let day:Date = new Date()
其他对象类型,用构造函数作为类型名字
其他类型
枚举类型
js
let order = {
id: 1,
name: "普通订单",
status: 0
}
//枚举,将各种状态,用枚举的方式列举出来。
enum orderState {
payError = 0,
paySuccess = 1,
payTimeout = 2
}
//不符合编码规范的
// 0 1 魔法数字(魔鬼数字),不能出现魔法数字
if (order.status == orderState.payError) {
} else if (order.status == orderState.paySuccess) {
} else {
}
枚举的状态一定有限的,可控的。
any类型
js
//当代码中无法明确指定数据类型的时候,你可以any占位。
let mode:any = true
const app:any = document.getElementById("app")
作业1:
js
题目一:使用原型或class的方式来实现js的链式调用,对数字进行加减乘除
案列:new myCalculator(100).add(1).reduce(100) ===》输出结果为1
作业2:
js
说明:定义一个函数,接受三个参数getMaxNumber(array,k,m){},找出第k大和第m大的数字之和。重复的数据也需要计算
比如:[1,3,4,5,4,6] k=1的时候获取到值为6(出现一次),m=3的时候获取到的只为4(出现2次),总和就是 sum = 6+4+4
作业3:
js
对数组进行排序,数组的数据格式不定。
>比如:[1,2,5,4,8] ===>返回 [1,2,4,5,8]
>
>比如:[1,3,[4,7],[6,5,9]] ===>返回 [1,3,4,5,6,7,9]
四、函数定义
在TS中函数研究两个内容
- 函数参数
- 函数的返回值
参数的传递方式
js
/**
* 参数:接受基本类型
* @param val
* @param val2
*/
function show(val:number,val2:string){
}
show(1,"xiaowang")
/**
* 参数:接受引用类型
* @param val
* @param obj
*/
function play(val:number,obj:{id:number}){
}
play(1,{id:1})
/**
* 接受函数类型
* @param fun
*/
function play2(fun:()=>void){
fun()
}
play2(()=>{})
/**
* 不定参数的场景
* @param args
*/
function play3(...args:number[]){
console.log(args[0]);
}
play3(1,2,3,4,5)
函数返回值
js
/**
* 函数的参数基本类型
* 函数返回值,
* @param val1
* @param val2
* @returns
*/
function play4(val1: number, val2: number):number {
return val1 + val2
}
const res = play4(1,2)
"123".substring(1,2)
const res2 = "1379002346".replace(/[13]/,"**")
箭头函数
js
const message = (params1:number):number=>{
return params1 * 2
}
message(2)
在设计工具类,在设计业务的时候,在函数调用过程中检测出你参数问题。
不至于项目要浏览器运行起来才知道自己参数传递错误
案列:
定义一个函数,接受一个数组,返回数组中最大值
js
function getMaxValue(args:number[]):number{
let max = args[0]
args.forEach(item=>{
max = max < item ? item : max
})
return max
}
let temp2:number[] = [1,5,7,9]
const max = getMaxValue(temp2)
console.log(max);
五、接口的概念
接口是一种约束、是一种规范。
比如后端接口:表达的后端返回的数据有什么约束、条件、格式等等。
在TS中接口,用于设计数据类型约束。复杂的数据类型,你可以用接口来约束。
属性类型接口
接口的定义
js
/**
* 设计一个接口,
* 我自己定义一种数据类型
*/
interface IStu {
id: number,
name: string,
gender: string,
classes: string
}
let students: IStu[] = [
{ id: 1, name: "杜欣", gender: "女", classes: "web35" },
{ id: 2, name: "袁令", gender: "男", classes: "web35" },
{ id: 3, name: "童瑶", gender: "女", classes: "web34" }
]
多个interface嵌套
js
/**
* 定义一个学生数组
* 学生:编号、名字、性别、班级
*/
/**
* 设计一个接口,
* 我自己定义一种数据类型
*/
interface IStu {
id: number,
name: string,
gender: string,
classes: IClasses,
phone?:string
}
interface IClasses {
cid: number,
name: string
}
let students: IStu[] = [
{
id: 1, name: "杜欣", gender: "女", phone: "344", classes: {
cid: 1, name: "web35"
}
},
{
id: 2, name: "袁令", gender: "男", classes: {
cid: 2, name: "web34"
}
},
{
id: 3, name: "童瑶", gender: "女", classes: {
cid: 3, name: "web33"
}
}
]
function getValue(students: IStu[], search: string) {
let stu = students.find(item => item.name == search)
return stu
}
const result = getValue(students, "童瑶")
//?.是一种新的运算符,ES2020这个版本推出来。 可选链运算符
// result是undefined或者null的时候 不会.id
console.log(result?.id);
export { }
练习:
- 定义一个员工数组(id、name、age、address)
- 定义一个函数,传递一个数组,找到年龄最大的员工
- 定义一个函数,传递一个数组和名字,根据名字模糊搜索
- 定义一个函数,按照年龄升序排列,返回这个数组。
js
/**
* 练习:
1. 定义一个员工数组(id、name、age、address)
2. 定义一个函数,传递一个数组,找到年龄最大的员工
3. 定义一个函数,传递一个数组和名字,根据名字模糊搜索
4. 定义一个函数,按照年龄升序排列,返回这个数组。
*/
interface IEmp {
id: number;
name: string;
age: number;
address: string;
}
let emps: IEmp[] = [
{ id: 1, name: "小王", age: 23, address: "成都" },
{ id: 2, name: "小张", age: 24, address: "武汉" },
{ id: 3, name: "小吴", age: 22, address: "北京" }
]
function getMaxAagEmp(emps: IEmp[]) {
const temp = emps.map(item => {
return item.age
})
//Math.max获取一堆数据最大值 Math.max(...temp)
const maxAge = Math.max.apply(emps, temp)
const emp = emps.find(item => item.age == maxAge)
return emp
}
function searchByName(emps: IEmp[], key: string): IEmp[] {
const temp = emps.filter(item => {
if (item.name.indexOf(key) != -1) {
return true
}
})
return temp
}
function orderByAes(emps: IEmp[]) {
emps.sort((a, b) => {
return a.age - b.age
})
return emps
}
类型断言
我比程序更清楚我的数据类型是什么。
两种语法
js
(obj as any).age
(obj as IStu).age
(<IStu>obj).age
案列
js
interface IUser {
id: number,
name: string
}
interface IStu {
id: number,
name: string,
age: number
}
//联合类型 union代表一种数据类型。
type union = IUser | IStu
/**
* 当编辑器推断出来的类型 不满足要求,报错的时候。强行给编辑器提示。
* 这个过程类型断言
* @param obj
*/
function change(obj: union) {
console.log(obj.id);
console.log((obj as any).age);
console.log((obj as IStu).age);
console.log((<IStu>obj).age);
}
change({ id: 1, name: "xiaowang" })
change({ id: 1, name: "xiaowang", age: 23 })
export { }
练习:
定义一个函数,传递日期对象,传递一个字符串格式,根据字符串格式返回对应的数据格式
js
format(new Date(),"yyyy-MM-dd") --->2023-10-31
format(new Date(),"yyyy/MM/dd") --->2023/10/31
format(new Date(),"yyyy/MM/dd hh:mm:ss") --->2023/10/31 15:14:20
代码
js
/**
format(new Date(),"yyyy-MM-dd") --->2023-10-31
format(new Date(),"yyyy/MM/dd") --->2023/10/31
format(new Date(),"yyyy/MM/dd hh:mm:ss") --->2023/10/31 15:14:20
字符串替换。"yyyy-MM-dd".replace("yyyy",date.getFullYear())
正则来匹配
*/
function format(date: Date, type: string): string {
const obj: any = {
"y+": date.getFullYear(),
"M+": date.getMonth() + 1,
"d+": date.getDate(),
"h+": date.getHours(),
"m+": date.getMinutes(),
"s+": date.getSeconds()
}
//根据obj这个对象中的内容 和type的内容进行匹配。
//type = "yyyy-mm-dd"
for (const key in obj) {
// /(y+)/
if (new RegExp("(" + key + ")").test(type)) {
type = type.replace(RegExp.$1, obj[key])
}
}
return type
}
const resultDate = format(new Date(),"yyyy-MM-dd")
const resultDate2 = format(new Date(),"yyyy-MM-dd hh:mm")
console.log(resultDate2);
可索引接口
这个模块用的比较少。遇到了理解他概念
概念:有时候你并不知道类型的所有属性名字,你只能确认属性值为number或者string的时候,你可以用可索引接口来约束我们代码
js
interface IUser {
[index:number]:string
}
可索引接口,可以表示两种数据类型,第一种数组,第二种对象。
js
array = [1,2,3]
array[0]
obj = {id:1,name:"xiaowang"}
obj["name"]
数组的可索引定义语法
js
/**
* [index:number]:代表这块内容是动态,不约束名字,值得类型被约束
* index:索引名字。默认都是这个名字,索引默认用number array[1]
*/
interface IArray {
[index:number]:number
}
const temparray:IArray = [1,3,4]
temparray[0]
对象得可索引接口语法
js
/**
* 当我不知道对象里面到存放什么属性,只能用可索引接口
*/
interface IObj {
[index:string]:string | number
}
const obj23:IObj = {}
obj23.id = 1
obj23.name = "xiaowang"
索引值得类型,索引值类型为string,代表允许我们通过string类型来作为索引获取数据
js
interface IObj {
[index:string]:string | number
}
const obj23:IObj = {id:1,name:"xiaoawng"}
obj23["id"]
练习题一:
- 确定有id和name,请取出来中值构造成对象
- 不确定到底传递过来有多少个键值对,都要封装为对象返回
js
http://127.0.0.1:8888?id=1&name=xiaowang
useLocation() ---> {search:"?id=1&name=xiaowang"}
{id:"1",name:"xiaowang"}
练习题二:
定义一个函数,接受电话号码,将中间得4位用*
隐藏起来 返回电话号码
比如:13890012345
--->138****2345
练习题三:
找出字符串中只出现一次的字母,返回第一个就可以。
js
console.log(firstAppear("abacdefeg")); 返回`b`
六、泛型
设计一个函数,要求进行数据排序
在TS程序设计过程中,约束越来越严格,导致参数得类型固定了。很多代码无法进行扩展
js
/**
*
* @param array
* @param orderBy
* @returns
*/
function sortData(array: number[], orderBy: number) {
if (orderBy == 1) {
array.sort()
} else {
array.sort((a, b) => {
return b - a
})
}
return array
}
sortData([1, 2, 3, 4, 5], 1)
sortData(["a", "b", "d", "c"], 2)
定义函数参数类型number,下次string类型得数组就无法使用这个函数。
提出了一个泛型得概念
泛型:泛指某个类型,数据类型也是动态可以变化得。
js
/**
*
* @param array
* @param orderBy
* @returns
*/
function sortData<T>(array: T[], orderBy: number) {
if (orderBy == 1) {
array.sort()
} else {
array.sort((a, b) => {
return b - a
})
}
return array
}
sortData<number>([1, 2, 3, 4, 5], 1)
sortData<string>(["a", "b", "d", "c"], 2)
多个泛型
js
function computed<T,K>(params:T,params2:K){
}
computed(1,2)
computed<string,number>("2",3)
泛型的使用,为了让数组能够存放指定数据类型。Array内部没有规定死类型,用户使用通过泛型来决定数组里面存放的值类型
js
let array:Array<number> = [1,2,3]
let array:Array<string> = [1,2,3]
案列:
js
/**
* 定义一个函数,获取一个数组,求最大值
* 不确定数组是number、string
*/
function getMaxValue<T>(array: T[]): T {
let max = array[0]
array.forEach(item => {
max = max < item ? item : max
})
return max
}
getMaxValue([1, 2, 3, 4])
getMaxValue(["a", "b", "c"])
export { }