TS是type+javascript(为js提供了数据类型支持)
一、什么是ts
1、写代码的同时可以发现错误,减少找bug、改bug时间,提升开发效率
2、程序中任何位置的代码都有代码提示
3、代码的可维护性,使得重构代码更容易
4、支持ECMAScript语法,优先体验最新的语法
最新技术栈:
React:TS+Hooks
Vue:TS+Vue3
二、安装编译TS的工具包
npm i -g typescript
yarn global add typescript
三、简化运行TS的步骤
1、直接在Node.js中中执行TS代码
npm i -g ts-node
ts-node xxx.ts
2、解决ts-node运行TS报错
tsc --init
ts-node xxx.ts
3、解决两个ts文件之变量名冲突
在非模块化环境下,TS会把.ts文件中声明的变量当作全局变量。当两个.ts文件中声明的变量名称相同,并且在VSCode中同时打开两个文件,会提示报错。
解决办法:在.ts文件最后加上export{}
解析:
(1)当TS看到export这样的模块化语法后,就会将该文件当作模板来解析,此时,再声明的变量就是该模板中的局部变量了
(2)export不需要导出任何内容,该代码的作用仅仅是为了让TS知道这是模块化环境
四、类型注解
1、将TS中的常用类型细分为两类:JS已有类型 TS新增类型
1.1、JS已有类型
let uniKey:symbol=Symbol()
let obj={
a:'yy'
}
obj[uniKey]='uu'
(a)number、string、boolean、null、undefined、symbol
symbol可以作为对象属性的键,防止与对象中其他键冲突。
(b)对象类型:object(包括数组、对象、函数等对象)
1.2、TS新增类型
(a)联合类型、自定义类型、接口、字面量类型、枚举、void、any等
2、函数类型参数和返回值
函数类型实际上指的是:函数参数和返回值的类型
为函数指定类型的两种方式
(1)单独指定参数、返回值的类型
//1、单独指定参数、返回值类型
// 函数声明
function fn1(num1:number,num2:number):number{
return num1+num2
}
// 箭头函数
const fn2=(num1:number,num2:number):number=>{
return num1+num2
}
(2)同时指定参数、返回值的类型
//2、同时指定参数、返回值类型
// 当函数作为表达式时,可以通过类似箭头函数形式的语法来为函数添加类型
// 这种形式只适用于函数表达式
// (1)创建函数自定义类型
type addFn=(num1:number,num2:number)=>number
// (2)使用自定义类型作为函数add的类型
const add:addFn=(num1,num2)=>{
return num1+num2
}
3、函数类型void和undefined
void和undefined类型不同
// 没有返回值 数据类型为void
const fn=(num1:number,num2:number):void=>{
return
}
// 返回undefined 和void不是同一种数据类型
const unfn=(num1:number,num2:number):undefined=>{
return undefined
}
4、对象类型
let person2:{name:string}={
name:'yyy'
}
// 使用type
type Myobj={
name:string
key:number
sayHi(name:string):void
sayHello:(age:number)=>void
}
let obj:Myobj={
name:'ww',
key:5,
sayHi(name){},
sayHello(age){}
}
应用
type typeConfig={
url:string;
methods?:string
}
const myAxios=(config:typeConfig)=>{}
myAxios({url:'',methods:''})
myAxios({url:''})
5、对象类型-interface vs type(注意:以type为先)
目标:能够理解interface和type的相同点和不同点
内容:interface(接口)和type(类型别名)的对比
(1)相同点:都可以给对象指定类型
(2)不同点:
接口,只能为对象指定类型
类型别名,不仅可以为对象指定类型,实际上可以为任意类型指定别名
interface IPerson{
name:string
age:number
sayHi():void
}
// 为对象类型创建类型别名
type IPerson1={
name:string
age:number
sayHi:()=>void
}
// 为联合类型创建类型别名
type NumStr=number|string
6、type合并类型,使用交叉类型来实现接口继承功能
//使用 交叉类型 来实现接口继承的功能
type Point3D=Point2D&{
z:number
}
7、元组类型Tuple
(1)目标:能够理解什么是元组
(2)使用场景:在地图中,使用经纬度来标记位置信息
可以使用数组来标记坐标,那么该数组中只有两个元素,并且这两个元素都是数值类型
使用number[]的缺点:该类型数组可以出现任意多个数字
(3)更好的元祖类型
元组类型是另一种类型的数组,它确切的知道包含多少元素,以及特定索引对应的类型
元祖类型可以确切的标记出有多少元素,以及每个元素的类型
let tup:[number,number]=[1,2]
8、类型推论
有些数据类型可以省略
9、字面量类型
let str='Hello TS'
const str1='Hello TS'
10、枚举类型
在贪吃蛇可以使用
//创建枚举类型
enum Direction {
Up=6,
Down=7,
Left=8,
Right=10
}
//使用枚举类型
const changeDirection=(dir:Direction)=>{}
changeDirection(Direction.Up)
枚举是TS为数不多的非JavaScript类型扩展的特性之一
因为:其他类型仅仅被当作类型,而枚举不仅作类型,还提供值(枚举成员是有值的)
也就是说,其他的类型会在编译为JS代码时自动移除。但是,枚举类型会被编译成js代码
11、any所有类型,一般不使用
12、类型推断
假设,页面中有一个a标签
因为getElementById()方法可以获取任何的HTML标签,所以,该方法的返回值类型时HTMLElement
但是这个返回值太宽泛,这时候就需要as来添加更加具体的类型
const link=document.getElementById('#Link') as HTMLAnchorElement
link.href
13、typeof运算符
typeof可以在js和ts中使用
let p={x:1,y:2}
console.log(typeof p);
function form(point:typeof p){}
form(p)
14、泛型函数
function fn<Type>(value:Type):Type{return value}
function fn2<T>(value:T):T{return value}
const num=fn(10)
console.log(num);
const str=fn2('uu')
console.log(str);
15、为泛型添加约束
第二种方式:指定约束
需求:能够访问参数value的length属性。
因此,我们可以来为Type类型变量添加一个约束,因为是需要访问length属性。
所以,只要让约束满足有length属性即可。
interface ILength{
length:number
}
function constraint<Type extends ILength>(value:Type):Type{
console.log(value.length);
return value
}
constraint({length:1})
constraint({length:1,a:'a'})
作用:用来获取对象中属性的值
因为第二个参数只能访问第一个参数对象中的属性,所以,需要为第二个参数的类型变量key添加约束类型
约束key的取值只能是对象obj中所有属性中的任何一个
keyof obj表示:获取到对象中的所有属性,最终,会得到一个对象obj中所有属性名称的联合类型
function getProperty<Obj,Key extends keyof Obj>(obj:Obj,key:Key){}
const obj={
name:'uu',
age:18
}
getProperty(obj,'name')
// typeof obj表示:获取obj在TS中的类型,也就是:{name:string,age:number}
// keyof表示获取该类型中所有键的集合,最终会得到一个联合类型
// keyof后面必须要跟一个类型,所以,此处obj不是类型,因此需要通过typeof来获取其类型
type Keys=keyof typeof obj
16、泛型工具类型
泛型工具类型:TS内置了一些常用的工具类型,来简化TS中的一些常见操作
说明:他们都是基于泛型工具类型实现的,主要有以下类型:
(1)Partial<Type>//用来构造一个类型,将Type的所有属性设置为可选
type Props={
id:string
children:number[]
}
// 构造出来的新类型Part结构和Props相同,但是所有属性都变为可选
type Part=Partial<Props>
// let p1:Props={}报错 因为里面属性是必选属性
let p2:Part={id:'p'}
console.log(p2);
(2)Readonly<Type>// 在属性前加readonly会让该属性变为只读属性
type Props2={
id:string
readonly children:number[]
}
let p1:Props2={id:'3',children:[12]}
type ReadonlyProps=Readonly<Props> //都变成只读属性
let p3:ReadonlyProps={id:'2',children:[1]}
(3)Pick<Type,Keys>
Pick工具类型有两个类型变量:1、表示选择谁的属性2、表示选择哪几个属性
其中第二个类型变量,如果只选择一个则只传入该属性名即可
第二个类型变量传入属性只能是第二个类型变量中存在的属性
interface Props3 {
id:string
title:string
children:number[]
}
type PickProps=Pick<Props3,'id'|'title'>