ts
2023-09-11 23:55:23 0 举报
AI智能生成
ts总结
作者其他创作
大纲/内容
ts实战
泛型约束后端接口参数类型
interface API{ '/book/detail':{ userid:number},'/book/login;:{ userid:number, username:string}}
function request(url:T,obj:API[T]]){ return axios.post(url,obj)}
request('/book/detail',{ userid:122})
ts基础
1.ts是什么
1.概念
ts是一种由微软开发的自由和开源的编程语言,它是js的一种超集,而且本质
上向这个语言添加了可选的静态类型和基于类的面对对象编程。
ts提供最新的和不断发展的js特性,包括Es2015和Es未来的提案的特性
比如异步功能和装饰器Decorators,以帮助建立健壮的组件
分支主题
2.ts和js的区别
分支主题
3.典型的ts的工作流程
分支主题
2.ts基础类型
1.boolean类型
eg:let isDone:boolean = false
相当于
var isDone = false
2.number类型
eg:let count:number =10
相当于
var count=10
3.string类型
eg:let name:string = 'semliker'
相当于
var name ='semlinker'
4.symbol类型
eg:const sym=Symbol()
let obj ={
[sym]:'semlinker',
}
console.log(obj[sym])
5.undefined和null
分支主题
6.any类型
不清楚是什么类型,就可以使用any类型。这些值可能来自于动态的内容
7.数组类型
let list:number[]=[1,2,3]
相当于
var list=[1,2,3]
如果这个数组里面写错类型了,let list:number[]=[1,2,'3'],字符型的3在数字型的数组里面会报错
如果数组里面想每一项放不同的数据,可以使用元组
6.元组类型
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同
let tuple:[number,string] = [18,'8块腹肌']
写错类型或者后面数组里面元素超出会报错
但是对元组使用数组方法时不会,比如push一个新元素,不会报越界错误
7.never类型
表示那些永不存在的类型
某些情况下,值永不存在,比如:函数执行异常,中断了程序运行,那这个函数永不存在返回值,或者函数无限循环,也无法运行到函数返回值那一步
3.ts函数类型
ts定义函数类型需要定义输入函数类型和输出类型,输出类型可以忽略,因为ts能根据返回语句自动推断出返回值类型
如果函数没有返回值,则默认返回void类型,void类型与any类型相反,表示没有任何类型
可选参数
参数后面加个问号,表示这个参数是可选的
function add(x:number,y:number,z?:number):number{return x+y}
输入参数类型z是可选类型,这个函数的输出类型是number
函数表达式写法
let add2 = (x:number,y:number):number=>{ return x+y}
函数赋值
函数不能随便赋值,不然会报错
想给一个函数赋值给另一个函数可以这样
let add2 = (x:number,y:number):number={ return x+y}
let add3 = (x:number,y:number):number=add2
4.interface
用于定义对象类型的,可以对对象的形状进行描述,定义interface需要首字母大写
interface Person={ name:String, age:Number}
定义person型对象
const p1:person={ name:'wang', age:12}
如果定义时里面有不是name和age的属性时就会报错,如果属性的类型错误也会报错
可选属性
interface Person={ name:string, age?:number}
这个对象中可以不去定义age属性
只读属性
interface Person={ readonly id:number}
id属性不能被修改
描述函数类型
interface Person{ (x:number,y:number):number}
const add:Person=(x,y)={x+y}
自定义属性
在inter face中,对象的属性必须和类型定义的时候保持一致,那如果一个对象中有很多属性暂时不确定的话,可以使用自定义属性
interface customProp{ [propName:string]:string}
const obj ={ a:'ww', b:'zzz', c:'xxx'}
如果这个时候的属性名定义成数字的话,就是一个类数组了,当然不是真的数组,数组方法是没有的
interface likearray={ [propName:number]:string}
const arr:likearray=['2'.'3','4']
鸭子类型,inter face又叫鸭子类型
只要数据满足interface的类型,就可以被ts编译通过
interface functiondackname{ (x:number):number, name:string}
functiondackname不仅描述了函数类型,而且它还带一个name属性,但是依旧可以通过编译
5.类
ts通过public,private,protected这三个类增强了js中的类,其他写法和js类似
基本写法
class person{ name:sting, constructor(name;string){ this,name=name}
}
继承
可以用extends实现继承
class student extends person{ speack(){ consloe.log(''') }}
继承之后student能访问person的属性和方法
如果student需要定义自己的属性的话,就需要用super继承父类的属性
class student extends person{ newname:string, constrcutor(name:string,newname:string){ super(name) this.newname=newname }}
不些super的话会报错
多态
子类对父类的方法进行重写
public
一个类里面默认所有的方法和属性都是public,所以它可写可不写
private
私有,只属于这个类资金,它的实例和它的子类都没有办法访问
protected
受保护的,继承这个类的子类可以访问,但是这个类的实例无法访问
static
静态属性,相当于类上的常量,实例和子类都不能访问
抽象类
只能被继承,但是无法被实例化的类
抽象类无法被实例化
abstract class animal(){
}const a = new animal()
报错
抽象类中的抽象方法必须被子类实现
抽象类用abstract关键字定义
this类型
类的成员方法可以直接返回一个this,方便链式调用
class step(){ step1(){ return this} step2(){ return this}}
let s = new step()s.step1().step2()
6.inter face和class的关系
inter face也可以用来约束class,约束class的时候需要用到implement
inter face music{ play():void}
class mymusic implement music{ play(){}}
定义了约束之后,class就需要满足接口上的所有条件
多个inter face约束同一个的时候可以这样
interface music{ play():void}
interface call{ call():void}
class x implements music,call={ play(){}call(){}}
处理公共属性和方法
不同的类有一些共同的属性和方法,使用继承也无法完成的时候,可以用inter face
约束构造函数和静态属性
interface circle{ new(x;number):void, p:number}
let c:circle = class c2{ static p:3.14, x:number,constructor(x:number){ this.x=x }}
7.枚举类型
定义一定范围内的一系列常量,可以给一组数据赋予名字
数字枚举
enum position{ left right, top, bottom}
ts会默认为值分配编号,0,1,2,3
position.left=0,position.right=1position.top=2position.bottom=3
字符串枚举
字符串枚举值要求每个字段的值必须为字符串,或者是枚举中的其他成员
enum msg { error='sorry,error', success="success", over=error, yes = success}
不能使用其他枚举中的值
反向映射
ts中枚举在编译之后其实是一个对象,包含正向映射key->value,也包含反向映射value->key,
enum sum{ success = 200, error=404,}
编译之后其实是
sum{ success:200, error:404, 404:error,200:success}
sum.success =200sum.error=404sum.200=success
反向映射只支持数字枚举
异构枚举
枚举中既有数字也有字符串
enum sum{ eror=200, suceess:'yes' }
枚举中成员也可以是表达式
enum sum{ yes=0, no=1, result=yes|no}
枚举合并
分开声明同一个名字的枚举时,ts会自动对该枚举进行合并
enum day{ left, rigjt,}
enum day{ top,bottom}
这个day会同时拥有left,right,top,bottom
left =0,right=1,top=2,bottom=3
8.类型推论
ts中没有明确指出类型的时候,会自动帮助提供类型
定义时不赋值
let a
a = 10a= '22'
当a只定义不赋值的时候,ts自动推导为any类型
初始化变量
let name ='sss'
name赋值的时候是字符串,所以ts自动推导为stirng类型
设置默认函数参数
function add (num = 1){ return num}
num会被自动推导为number类型,这个时候如果传了其他类型的num会报错,eg: add('12'),会报错
决定函数返回值
如果函数不写返回值,会默认是void类型
function add(num =1 ){ return num }
add函数的返回值也会被推导为number类型
如果将add函数的返回值约束为其他类型,会报错
interface add{ (num:number):string
let add1:add = add
这个时候会报错
最佳通用类型
需要从几个表达式里面推断类型的时候,会使用这些类型推断出一个最合适的通用类型
let arr = [0,1,null,'ss']
arr会被推导为 let arr:(string|null|number)[]
9.内置类型
js的内置对象可以在ts中直接被当作定义好的类型,
js的八种内置类型;string,number,boolean,null,undefined,symbol,bigint,obj
es的内置对象
例如array,date,error等对象
bom和dom
例如:HTMLElement,NodeList,MouseEvent等
ts的预置了一个核心库的定义文件,用于定义所有浏览器环境捉弄需用到的类型
ts进阶
高级类型一
1.联合类型 |
联合类型可以通过管道 | 来将变量设置为多种类型,赋值的时候可以根据设置类型来赋值
定义变量
var x:string|numberx = 'sss'x=12
赋值其他类型会报错
联合类型数组
var arr:number[]|string[]
函数参数
function add(x:number|string){}
2.交叉类型 &
如果对对象形状进行扩展,可以使用交叉类型 &
例:person 有name属性,而man在拥有name属性外还有age属性
inter face person { name:string}
type man=person&{age:number}
联合类型是指可以去多个类型中的一种,而交叉类型是指把多个类型进行合并,类似于interface的extends,用于对象扩展
3.类型别名 type
相当于给某类型取个别名,方便后面使用
eg:type NameOrAge = number|string
那么后续就可以直接用NameOrAge作为我们的类型了
function add(n:NameOrAge){ return n}这个n的类型其实还是number|string
几种例子
type name =string
type item =number|string
type person ={name:name}
type man = person&{age:number}
type manitem =person & {it:string}
type manlist =[man,manitem]
const list:manlist = [ {name:'sss',age:12}, {name:'sssaaa',it:'ssy''}]
与interface的不同和相同点
4.类型保护
5.类型断言
值as类型
6.字面量类型
可以定义一些常量
type butttonsize="'大'|'中‘|'小''"
这样就只能从这些常量中取值,取别的会报错,const a:buttonsize="大"
.ts泛型
1.为什么需要泛型
可以使用泛型来创建可重用的组件,一个组件可以支持多个类型的数据。
2.基本使用
function add(x:T):T{ return x}
输入输出类型统一,可以输入输出任何类型,但是如果输入输出类型不一致就会报错
const x:string=add(22)
T像一个占位符或者说一个变量,在使用的时候可以将定义的类型像参数一样传入,它可以原封不动的输出
一看到<>这个就是泛型
使用的时候可以用两种方法指定类型
子主题
add('hello')
定义add函数的T为字符串类型
2.ts类型推断,自动推导类型
add('hello')
rs类型推导,自动推导类型
type和inter face写法
type a=(x:T):T
interface tadd{ (x:T):T}
默认参数
给泛型添加默认参数
interface add{ (a:T):T}
多个函数参数
function add(x:[T,U],y:[U,T]){ return [x,y]}
这里的U和T效果一样,也是占位符
3.约束泛型
如果有个函数function add(x:T):T{},要求这个函数的传参x比如有length属性,那么就可以跟inter face结合来约束类型
分支主题
就能约束泛型
interface length{ length:number}
function add (x:T):T{}
这里的T就一定会有length属性了
作用
1.确保属性存在
2.检查对象上的键是否存在
keyof ,用于获取某种类型的所有键,其返回类型是联合类型
interface person{ name:string, age:number}keyof person
keyof perso 拿到的是name,age
k extends keyof T
确保k一定是T中的键
4.泛型的一些应用
泛型可以在定义函数、接口或者类的时候,不预先指定类型,而是使用的时候再指定类型
泛型约束类
class stock{ private data:T[]=[], pop(x:T):T{ data++ }, push(x:T):T{ data--}}
泛型不能约束类的静态成员
泛型约束接口
inter face dack{ key:T value:U}
const k1:dack={key:7,value:'xx'}
泛型定义数组
cont arr:Array=[1,2,3]
等同于
const arr:number[]=[1,2,3]
5.泛型的好处
函数和类可以轻松支持多个类型,增强程序扩展性
不必写冗长的联合类型,增强代码的可读性
灵活控制类型之间的约束
6.泛型条件类型
T extends U?x:y
如果t能赋给u,那么是x,否则是y
infer关键字
T extends interface?V:never
当T满足T extends interface这个约束的时候,我们会用infer声明一个类型变量V,并返回这个类型,否则是never
7.泛型工具类型
Partial
将某个类型里面的属性全部变为可选
type partial = { [P in keyof T]?:T[p]}
例子:interface todo{ name:string, num:number}
function newtodo(x:partial){ return x}newtodo({name:'wss'})
Record
Record,将k中所有的属性的值转换为T类型
type Record{ [p in K]:T}
例子:interface page{ title:string,}type pageTitle="'name'|'about'"
const x:Record{ name:{title:'name'}, about:{title:'about'}}将pageTitle中所有的属性转换成了page类型
Pick
Pick
将T中的子属性挑出来,变成包含这些子属性的子类型(有点像截取)
type Pick={ [p in K]:t[p]}
例子:interface todo{ name:string, title:string, num:number} type todochild=Pickconst todochld1:todochild={ name:'132', title:'sss'}
将todo中的name属性和title属性挑出来作为一个新的子类型,赋给todochild
Exclude
Exclude将T联合类型中属于U联合类型的属性移除掉
type Exclude=T extends U?never:T
例子:type t = Exclude
t的结果是 "b''|''c''
ReturnType
ReturnType获取函数T的返回类型
例子:type t0=ReturnTypestring>.t0的结果是string
type t1 =ReturnTypet1的结果是any
type t2 =ReturnTypet2的结果是any
type t3 = ReturnTypet3的结果是error
type t4 = ReturnTypet4的结果是Error
高级类型二
索引类型
关键字
keyof(索引查询)
用于获取某种类型的所有键盘,返回类型是联合类型
interface person{name:string,age:number}type s=keyof persons的结果"name"|"age"
T[k] (索引访问)
person['age']结果是number
extends(泛型约束)
映射类型
将一个类型映射成另一个类型
关键字 in 用于对联合类型进行遍历
partial将类型中的属性映射成可选的
Readonly将类型中的所有属性映射成只读
type Readonly={ Readonly [p in keyof T]:T[p]}
pick类型抽取对象子集,挑选一组属性组成新的类型
Record类型
条件类型
T extends U?x:y
Exclude
Exclude返回T联合类型中不属于U联合类型的部分
Extracr
提取联合类型T和联合类型U中的所有交集
type Extract=T extends U?T:never
工具类型
omit
omit从类型T中剔除U中的所有属性
interface person={ name:string, age:number}
type imit =omit
imit的结果为{ name:string}
type omit ==Pick>
type omit =={ [P in Exclude]:T[P]}
NonNullable
NonNullable过滤T中的所有null和undefined属性
type NonNullable= T extends null|undefined?never:T
Parameters获取函数的参数类型,将参数类型放在元组中
type T1 = Parameter]T1的结果为[arg1:number,arg2:string]
type T2 = Parameters{}>T2的结果为[string]
type T3=Parameter[]>T3的结果为[]
ReturnType获取函数的返回值类型
类型体操是什么
ts高级类型会根据类型参数求出新的类型,这个过程会涉及一些类型计算逻辑,这写逻辑就叫做类型体操,但是这个不是正式概念,只是社区的戏称
ts声明文件
declare
使用第三方库的时候,很多三方库不是用ts写的,我们需要引用它的声明文件,才能获得对应的代码补全
例如在TS中直接使用Vue会报错
这个时候就需要decalre关键字来定义Vue的类型了
eg:decalre class vue{ options:vueoptions, constructor(options:vueOptions)}
.d.ts
通常我们会把声明语句放在单独的文件中,例如vue放在(vue.d.ts)中,这些声明文件以.d.ts作为后缀
一般来说ts会解析项目中所有的*.ts文件,其中就包含.d.ts的文件,所以在我们将vue.d.ts文件放入项目的时候。其他所有的*.ts文件都能获取vue的类型定义了
使用三方库
并不是所有三方库文件在使用的时候都需要用declare声明文件,那样太多了会出现一大堆的declare文件
所以这个时候我们就需要看社区里有没有三方库的TS类型包了(一般都有)
社区使用@types统一对三方库的声明文件进行管理
例如:npm install @types/lodash -D
0 条评论
下一页