前置:

如何使用vscode调试ts?

  1. webpack+babel(常用)
  2. Vite(常用)
  3. tsc(typescript compiler)

类和类型:
JS中,类型 就是数据种类的区分,在JS中有八种数据类型
类 针对对象类型object 进行分类

ts类型标明一般首字母大写,除了特定的几个情况如unkown/()=>{}等
ts类型:在js八种类型的基础上加上 元组、any、never
(object类型基本不用,因为object类型种包含更具体的内容,写object没有什么意义)
image.png

ts面试题集:

any、unknown、never 区别

any 和 unkown 顶级类型

两者都是顶级类型,任何类型的值都可以赋值给顶级类型
TS学习 - 图2

  1. //不报错,从右到左兼容
  2. let foo:any = 123
  3. let bar:unkown = 123
  4. const value:unkown = 'npc'
  5. const someString:string = value //报错,value为unkown类型不可兼容其他
  6. const value:any = 'npc'
  7. const someString:string = value //不报错,any不做任何类型检查
  8. //类型收窄
  9. const value:unkown = 'npc'
  10. const someString:string = value as string //不报错,先把unkown收窄为string再赋值即可兼容
  11. //通过断言让类型收窄

never 底类型

不应该出现的类型,一般出现了则表示此处代码出错
TS学习 - 图3

  1. interface Foo {
  2. type:'foo'
  3. }

总结

  • 顶类型可以被赋值为任何东西,底类型不可以被赋值为任何东西
  • unkown比any类型检查更为严格,一般使用unkown需要结合断言做类型收窄

any 没有任何限制(永远都不知道它是什么类型)

unkown 声明的时候不知道它是声明类型,要使用的时候需要明确指定类型(现在不知道它是什么类型,但使用它的时候就得知道它是什么类型)

  1. type c = {name:111}
  2. let b:unkown = JSON.parse('name':'npc')
  3. console.log(b as c).name

never 表示空集,什么都没有,不应该存在的类型,代码出现never表示此处代码出错

  1. type Dir = 1|2|3|4|undefined
  2. let dir:Dir
  3. switch(dir){
  4. case 1:
  5. break
  6. case 2:
  7. break
  8. case 3:
  9. break
  10. case 4:
  11. break
  12. case undefined:
  13. break
  14. default:
  15. console.log(dir)
  16. break
  17. }
  18. type X = number & string //交集为空,即never

void 用于函数返回值为undefined、null或者无return,简单说void就是undefined

  1. let print:()=>void = function (){
  2. console.log(1)
  3. return undefined
  4. }

type 和 interface 区别

  1. 组合方式:interface使用extends来实现继承;type 使用 & 来实现联合类型
  2. 扩展方式:interface 可以重复声明和添加新字段用来扩展;type一个类型只能声明一次,之后后无法更改
  3. 范围不同:type 适用于基本类型和对象类型,interface 一般用于对象类型
  4. 命名方式:interface 会创建新的类型名,type 只是类型别名,即给类型取了个别名,并没有新创建类型
  1. interface B {
  2. b:string
  3. }
  4. interface A extends B {
  5. a:stirng
  6. }
  7. const a:A = {
  8. a:'hi'
  9. b:'npc'
  10. }
  11. //等同于
  12. type BB ={
  13. bb:string
  14. }
  15. type AA ={
  16. aa:string
  17. } && BB
  18. const aa:AA ={
  19. aa:'hi'
  20. bb:'npc'
  21. }
  1. //1.js
  2. interface A {
  3. a:string
  4. }
  5. //2.js
  6. interface A {
  7. a:string
  8. }
  9. //3.js
  10. const a:A = { //1.js和2.js两个interface会自动合并,即可扩展
  11. a:'hi'
  12. b:'npc'
  13. }
  14. //1.js
  15. type A = {
  16. a:string
  17. }
  18. //2.js
  19. type A ={
  20. a:string //报错,不可重复声明,即不可扩展,不可变,类似const声明
  21. }
  1. type UserName = string
  2. interface UserName extends string {}//报错
  1. type X = number
  2. const x:X = 1
  3. type Y = typeof x // type Y = number ,X只是number类型的别名,没有真正存在
  4. //可以使用类型别名为任何类型指定名称,而不仅仅是对象类型
  5. type A = typeof x //熟记此处 typeof 用法

注意:接口interface可以定义任意key

  1. export interface Ilist {
  2. product_id:string,
  3. ...
  4. [propname:string]:any //以防后端从新增字段不同于上面
  5. }

泛型

广泛的类型,当作函数去理解
泛型就是给类型传参,传入的参数就是“泛型变量/类型变量”
**构造函数<描述构造函数>**

  1. const a:Array<number> = [1,2,3]
  2. //类比JS
  3. type A = 'hi' | 123 //TS
  4. let a =['hi',123] //JS
  5. let fn = (x:number) => x+1
  6. type F<T> = T | T[]
  7. type FNumber = F<number>
  8. type FString = F<string>
  9. type Add<T> = (a:T,b:T)=>T //定义
  10. const addN:Add<number> = (a,b)=> a+b //调用
  11. const addS:Add<stirng> = (a,b)=> a+ '' + b
  1. number[] === Array<number>
  2. //Array的底层,实际上是interface定义的函数
  3. interface Array<T> {
  4. [n:number]:T
  5. }

注意:泛型可以嵌套泛型,也可以传多个参

元组

用于固定数组的长度,需要指定位置指定每个元素的类型

  1. let p:[number,number] = [100,200]
  2. p = [1,2,3,4] //报错
  3. p = [1,2]
  4. console.log(p as any).push(3)// 强制修改,使用断言

枚举

很少使用

  1. //不推荐写法
  2. enum Dir2 {东,南,西,北}
  3. let d:Dir2 = Dir2.东
  4. let d2:Dir2 = Dir2.西
  5. console.log(d)
  6. //推荐以下写法
  7. type Dir = '东'|'南'|'西'|'北'
  8. type Dir3 = 0|1|2|3
  9. let dir:Dir = '东'
  10. let dir2:Dir = '南'

断言

联合类型| 和 交叉类型&(类型体操)

关于类型的组合,对类型进行编程

联合类型|

二选一

联合了 又如何做区分?

  1. type A ={
  2. name:'a';
  3. age:number
  4. }
  5. type B ={
  6. name:string;
  7. gender:string
  8. }
  9. //情况一:入参为简单数据类型可以用typeof做类型区分
  10. const f = (n:number|B)=>{
  11. if(typeof n === 'number'){ //类型收窄(类型可收窄至具体某值)
  12. n.toFixed()
  13. }else{ //类型推测
  14. n.name
  15. }
  16. }
  17. //情况二:入参为复杂数据类型 需要找到共同key做类型分支
  18. const f = (n:A|B)=>{
  19. if(n.name === 'a'){ //类型区分(俩类型至少有一个相同key)
  20. }else{
  21. }
  22. }

交叉类型&

不能用于简单数据类型,因为简单数据类型是没有交集的,则会显示never
一般用于object,但需要具体描述object
表示相加

怎么声明div的类型

如果项目种tsconfig.json文件声明了”lib”:[“DOM”],ts自带类型模糊匹配,自带很多内置的复杂类型

  1. const div1:HTMLdivElement

TS工具类型 Partial、Required、Readonly、Exclude、Extract、Omit、ReturnType 的作用和实现

partial 部分类型
Required 必填类型

针对对象类型的key
Pick 挑选类型
Omit 排除key类型

针对简单类型
Extract 提取类型
Exclude 排除类型

Readonly 只读类型
ReturnType 返回值类型
Record 记录key和value类型

  1. interface User {
  2. id:stirng;
  3. name:string;
  4. }
  5. const user:User = { //报错,因为user上传至服务器才有id,除了?可选,还有其他解决?
  6. name:'npc'
  7. }
  8. //改为Partial,变为User的一部分,即User类型的每个key都是可选的
  9. const user:Partial<User> = {
  10. name:'npc'
  11. }
  1. //和Partial 作用相反
  2. const user:Required<User> = {
  3. name:'npc' //报错,id必填
  4. }
  1. interface User {
  2. id:string;
  3. name:string;
  4. age:number
  5. }
  6. type God = Pick<User,'id'|'name'> //挑选
  7. //从User类型中挑选出id和name两个子类型构成God类型
  8. type God = Omit<User,'id'> //排除的是key 引用
  1. type Dir = '东'|'南'|'西'|'北'
  2. type Dir2 = Exclude<Dir,'北'>
  3. type Dir3 = Extract<Dir,'东'|'南'>//作用相反,有南则提取,没有则不提取
  1. function f(a:number,b:number){
  2. return a+b
  3. }
  4. type A = ReturnType<typeof f> //泛型中必须传类型typeof f,而不是传值f
  1. type a = Record<string,number> //a类型的所有key为stirng,所有value为number
  2. //且key类型只能有string|number|symbol

as const类型收窄

一旦声明后续不可强制再变,如改为any类型后再push
image.png

  1. const a = [1,2,3] //类型推测 a:number[]
  2. const a = [1,2,3] as const //类型推测 a:readonly [1,2,3] 只读的,收窄至静态常量


tips:查看这些工具函数源码,相当精炼

如何给不同数据加type

typeof两个bug

  1. typeof null 返回字符串object
  2. typeof fn 返回字符串functuon

如果遇到object类型,使用具体的class进行描述,即Array 和()=> ?(不能写Function)

class是类型type还是值value?

答案全都是,class既是类型又是值

  1. class A {
  2. }
  3. //const x:类型 = 值
  4. const B = A // class A是值(对于JS来说)
  5. const a:A = new A() //class A 是类型(对于TS来说)