TypeScript

TypeScript

类型

//只能赋值给同类型或者被同类型赋值
let a:number = 1
//只能赋值给同类型或者被同类型赋值
let a:string = '1'
//只能赋值给同类型或者被同类型赋值
let a:null = null
//只能赋值给同类型或者被同类型赋值
let a:undefined = undefined
//只能赋值给同类型或者被同类型赋值
let a:boolean = true/false
//只能赋值给同类型或者被同类型赋值
let a:symbol = Symbol()
//只能赋值给同类型或者被同类型赋值
let reg:RegExp = new RegExp(/\w/)
//只能赋值给同类型或者被同类型赋值
let error:Error = new Error('错误')
//只能赋值给同类型或者被同类型赋值
let xhrL:XMLHttpRequest = new XMLHttpRequest()
//只能赋值给同类型或者被同类型赋值
let date:Date = new Date()
//只能赋值给同类型或者被同类型赋值
let div:HTMLDivElement = document.querySelector('div')
//只能赋值给同类型或者被同类型赋值
let div:NodeList = document.querySelector('div')
//只能赋值给同类型或者被同类型赋值
let local:Storage = localStorage
//只能赋值给同类型或者被同类型赋值
let lo:Location = location
//只能赋值给同类型或者被同类型赋值
let promise:Promise<string> = new Promise((r) =>r('s'))
---------------------------------
//只能赋值给同类型,可以被其他类型赋值
let a:any = any()
//只能赋值给同类型或者any类型,可以被其他类型赋值,无法读取任何属性或者方法
let a:unknown
let b:unknown
b = a
//只能赋值给同类型,可以被除(null和undefined)其他类型赋值
let a:Object
let b:{} //字面量写法,不能修改值,少用
b = a
//只能赋值给同类型,可以被除(string和number和boolean)其他类型赋值
let a:object
let b:object
b = a

数组,| 操作符,?操作符

//两种写法,表示a只能是单一类型数组
let a:number[] // 这种写法用的多
let a:Array<string> //这种写法写react不推荐
//表示a是数字类型数组或者字符串类型数组,|操作符表示选择意思
let a:(number | string)[]
//表示a可以是数字类型或者是字符串类型数组
let a:number | string[]
//二维数组
let arr:number[][] = [[1],[2],[3]]
//表示a是固定长度数组(元组)
let a:[number,string] = [1,'1']
//表示obj有值就调用forEach方法,没有值(underfind)就不调用。
Array?.forEach() // 也可以用if判断
if(Array){
Array.forEach()
}

函数,?操作符,默认参数

//三种写法,描述形参类型,表示函数返回值类型为void
function a(name:string = 10,age:number):void {} //具名函数,默认参数
let a = (name:string,age?:number):void => {} //箭头函数,可选参数(可选参数一定要排在最后面)
let a:(name:string,age:number) =>void  = (name,age) => {} //具名或者箭头函数
---------------------------------
//参数是对象,用interface定义
interface a {
  name:string
  age:number
}
function b(params:a):a {
  return params
}
b({name:'小红',age:23})

对象
对象中声明的属性和方法,赋值时不能多也不能少,属性可以设置只读,方法不行。

//两种写法,描述对象类型
let a:{          
  readonly name:string //表示只读,不能修改
  age:number
  sayHi:(x:number) => void //表示sayHi是函数类型
  xx(y:string):void //表示xx是函数类型
} = {
  name:'小明',
  age:2,
  sayHi(x:number){},
    xx:(y:string) =>{}
}
---------------------------------
//下面写法很鸡肋,没什么屁用
let user1: {
  0:string
  1:number
} 
= ['1',1,] 

接口,?可选操作符,|操作符,this指定类型
接口中声明的属性和方法,实现时不能多也不能少。
接口同名会重合,多余的属性可以用索引签名占位,可以用extends继承。

//两种写法,描述对象类型
interface user {
  name:string
  age:number
  sayHi:(x:number) => void //表示sayHi是函数类型
  xx(y:string):void //表示xx是函数类型
}
//下面写法很鸡肋,没什么屁用
interface user1 {
  0:string
  1:number
}
let a:user1 = ['1',1,] 
---------------------------------
//接口可以通过extends 继承并添加自己的属性和方法
interface user {
  name:string
  age:number
  sayHi:(x:number) => void //表示sayHi是函数类型
  xx(y:string):void //表示xx是函数类型
}
interface user1 extends user{
  zz:boolean
  yy:(x:number) => void //表示yy是函数类型
}
---------------------------------
//接口同名会重合,索引签名,只校验接口中具体的声明,readonly表示只读。
interface user{
  name:string | number // | 表示name可以是string类型或者number类型
  age:number
  readonly id:string // 表示只读,不能修改
}
interface user{
  name:string
  a?:number  // ? 表示可选,有也行,没有也行
  add:(this:Obj,num:number) =>void //this指定类型
  [propNmae:string]:any //索引签名,只验证之前的内容
}
let a:user = {
  name:'小红', // 1
  age:1,
  a:1,
  b:'1',
  c:1,
  add(this:Obj,num:number){
  this.user.push(num)
  }
}
---------------------------------
//&操作符 表示连接
interface Pople {
  name:string
  age:number
}
interface Man {
  sex:number
}
let a= (man:Pople & Man): void =>{
  console.log(man)
} 
a({name:'小红',age:1,sex:2})

类型断言 as 两种写法 type类型别名
使用type关键字定义,type用&符扩展,type也可以和接口联合使用

let fn = (name: number | string):void =>{
  console.log((name as string).length) //as写法
  console.log((<string>name).length) //<>写法
}
---------------------------------
//类型别名(数组形式)
type a = (number | string)[]
let b:a = [1,'3']
---------------------------------
//第二种写法
let a = [1]
let b: typeof a
---------------------------------
//类型别名(对象形式)
type a = {
  name:string
  age:number
}
let n:a = {
  name:'1',
  age:1
}
---------------------------------
//第二种写法
let a = {
  s:1
}
let b: typeof a
---------------------------------
//第三种写法(鸡肋,没什么屁用)
type a = {
  0:string
  1:number
}
let n:a = ['1',1]
---------------------------------
//type和接口联合使用
interface a {
  name:string
}
interface b {
  age:number
}
type c = a & b
let d:c = {
  name:'1',
  age:2
}
---------------------------------
//type高级用法 extends 包含的意思 1是否包含在number中
type num = 1 extends number ? 1 :0

class
class类成员必须声明,constructor中this才能访问,constructor不需要指定返回值类型,类的继承用extends,类实现接口用implements,
类中有readonly 只读,private (只能在类中访问,实例对象不可直接访问),protected (只能在类和子类中访问,实例对象不可直接访问)
static(静态方法,类身上的方法),abstract 定义的类和属性还有方法都不需要具体实现,不能实例化,只能继承,子类必须实现抽象类中abstract 定义的方法和属性。

interface Man {
  getName:(name:string) =>string
  readonly name:string //只读
}
// 类实现接口用implements
class People implements Man { //类实现接口用implements
  readonly name:string = '小红' //只读
  private names:string = '小明' //只能在类中访问,实例对象不可直接访问
  protected age:number = 20 //只能在类和子类中访问,实例对象不可直接访问
            className:string = '三年二班'
  constructor(className:string) {
    this.className = className //class类成员必须声明,constructor中this才能访问,constructor不需要指定返回值类型
  }
   setName():string {
    return this.names //可以通过公共方法return方式访问私有变量
  }
  getName = (name:string):string => {
    return name
  }
}
// 类的继承用extends 
class Wanman extends People {
      constructor(){
      super() //内部原理通过父类的prototype.constructor.call实现
      }
      getPeopleName():number {
        return this.age
      }
      setPeopleName = ():string => {
        return this.name
      }
}
---------------------------------
//抽象类,abstract 定义的属性和方法都不需要具体实现,不能实例化,只能继承,子类必须实现抽象类中abstract 定义的方法和属性
abstract class people {
  name:string
  constructor(name:string){
    this.name = name
  }
  getName():string{
    return this.name
  }
  abstract int():void
}
// 实现类
 class Man extends People {
  int (): void {
    console.log(1)
  }
 }

枚举
(字符串和数字两种类型) 只读不能赋值和修改 值默认从0自增,也可以自己设置
数字类型可以全部设置默认值也可以部分设置默认值,字符串类型必须全部设置默认值

enum penple {name,age = 1 } //数字类型可以全部设置也可以部分设置
enum penples {name = 'hao',age = 1 } //字符串类型必须全部设置
let a:penple 
a = penple.age
a = penple.name

Ts类型兼容性,Ts采用结构化类型系统,而不是表明类型系统,结构相同Ts就认为是同一类型 接口 函数 类

class a {
  x!:number
  y?:string
    z?:boolean
}
class b {
  x!:number
  y?:string
}
let C:b = new a()

never
用来兜底报出错误

type A = '唱'|'跳'|'rap'
function kun(value:A) {
  switch(value){
    case '唱':
      break
      case '跳':
      break
      case 'rap':
      break
      default:
        //兜底逻辑
        let error:never = value
        break
  }
}

Symbol

let a1:symbol = Symbol(1)  //接受参数的类型  string | number | undefined
let a2:symbol = Symbol(1)
console.log(a1 === a2) // false Symbol 内存地址是唯一的
console.log(Symbol.for('1') === Symbol.for('1')) //true for方法查看全局'1'是否存在,存在直接用,不存在创建一个。
Object.getOwnPropertySymbols() //可以读取对象上Symbol,不能读取普通属性
Reflect.ownKeys() //既可以读取Symbol也可以读取普通属性。

生成器,迭代器
async await底层运用生成器

// 生成器
function* gen() {
  let name:string = "小红"
  let age:number = 22
  let className:string = "小学一班"
  yield Promise.resolve(name)
  yield age
  yield className
}
let man = gen()
console.log(man) //gen {<suspended>}
console.log(man.next() //{value: Promise, done: false}
console.log(man.next().value) //Promise {<fulfilled>: '小红'}
console.log(man.return()) //{value: undefined, done: true}
console.log(man.throw('错误')) //caught 错误
---------------------------------
// 迭代器 可以用for of 
let arr:number[] = [1,2,3,4,5]
let a1:number = arr[Symbol.iterator]().next().value
console.log(a1) //1
// 迭代器语法糖可以用for of(只能遍历一层,无法深层次),对象不能使用,对象身上没有[Symbol.iterator]()方法。

for (let a2 of arr) {
  console.log(a2) //1,2,3,4,5
}

可迭代对象是Interator接口的实现,必须有两个协议,可迭代协议和迭代器协议,可迭代协议:对象或其原型链上必须有一个名叫Symbol.iterator的属性。该属性的值为无参函数,函数返回迭代器协议。迭代器协议:要求必须实现一个next()方法,该方法返回对象有done(boolean)和value属性。
ES6解构语法糖分为枚举解构(对象解构语法)和迭代解构(数组解构语法),如果js值没有Symbol.iterator方法,用迭代解构语法运行会抛出错误,用枚举解构语法不会抛出异常,如果js值有Symbol.iterator方法,用迭代解构语法可以,用枚举解构语法也可以。
泛型

//两种写法T[]或者Array<T>,含义相同。
function a<T extends number>(value:T[]):Array<T> {
  return value
}
a<number>([10])
---------------------------------
//多个泛型写法
function add<T = number,K = number>(a:T,b:K):(T|K)[] {
  return [a,b]
}
---------------------------------
//泛型约束,函数继承接口形式
interface LookName{
  length:number
}
function a<T extends LookName>(value:T[]):T[] {
  value.length
  return value
}
a<string>(['s'])
---------------------------------
//泛型约束,接口形式
interface a<T> {
  name:string
  age:T
}
let b:a<number> = {
  name:'1',
  age:1
}
---------------------------------
//泛型约束,类型别名形式
type A<T> = string | number | T 
let a:A<boolean> = true
---------------------------------
//泛型约束,extends keyof形式
interface a {
  name:string
  age:number
}
let perpon:a = {name:'jack',age:18}
function a<T, K extends keyof T>(obj:T,key:K) {
  return obj[key]
}
a(perpon,'name')
---------------------------------
//in 只能在类型别名中使用,不能在接口中用,类似for in循环
interface Data {
  name:string
  age:number
  sex:number
}
type Options<T extends object> = {
  [Key in keyof T]?:T[Key]
}
type B = Options<Data>

命名空间
防止变量命名冲突

namespace B {
  export let a = 2
}
//嵌套类型命名空间,重名会合并
namespace B {
  export namespace C{
    export let D = 1
  }
}

混入mixins

// 对象类型mixins
interface Name {
  name:string
}
interface Age {
  age:number
}
interface Sex {
  sex:number
}
let a:Name = {name:'小红'}
let b:Age = {age:1}
let c:Sex = {sex:2}
let obj = Object.assign(a,b,c)
---------------------------------
//class类 类型mixins
class A {
  name!:string
  changeType!:() => void 
}
class B {
  type!:boolean
  getName():boolean {
    return this.type
  }
}
class C implements A,B {
  name:string = "小红"
  type:boolean = true
  changeType!:() => void 
  getName!:() => boolean
}
let c = new C()
console.log(c)
function mixins(cur:any,item:any[]) {
  item.forEach(item =>{
    console.log(item) //classA,classB
    Object.getOwnPropertyNames(item.prototype).forEach(name=>{
      cur.prototype[name] = item.prototype[name]
    })
  })
}
mixins(C,[A,B])

装饰器
不破坏类的结构,添加方法或者属性

// 装饰器工厂 函数柯里化(解决传参问题)
let Bases = (name:string) => {
  let fn:ClassDecorator = (targe) =>{
    targe.prototype.name = name
  }
  return fn
}
@Bases('小红') 
// 方法装饰器
let Get = (url:string) =>{
  let fn:MethodDecorator = (target,key,des:PropertyDescriptor) =>{
    console.log(target) //{constructor: ƒ, getList: ƒ} Http实例对象
    console.log(key) //getList
    console.log(des) //{writable: true, enumerable: false, configurable: true, value: ƒ}
  }
  return fn
}
// 参数装饰器
let Result = () =>{
  let fn:ParameterDecorator = (target,key,index) =>{
    console.log(target) //{constructor: ƒ, getList: ƒ} Http实例对象
    console.log(key) //getList
    console.log(index) //参数所在的位置
  }
  return fn
}
// 属性装饰器
let Name:PropertyDecorator  = (target,key) =>{
    console.log(target) //{constructor: ƒ, getList: ƒ} Http实例对象
    console.log(key) //getList
}
class Http {
  @Name
  name:string
  constructor(){
    this.name = "小红"
  }
  @Get('123')
  getList(@Result() data:string){
    console.log(data)
  }
//...很多方法属性
}

Proxy Reflect
是ES6新增的,它是一个类,是用于帮助我们创建一个代理对象,他与Object.defineProperty最大的区别就在于Object.defineProperty直接监听对象的属性,proxy是监听整个代理对象。Reflect是一个对象,字面意思是"反射",它主要提供了很多操作JavaScript对象的方法。
new Proxy(obj,handler)
handler.get():属性读取操作的捕捉器。
handler.set():属性设置操作的捕捉器。
handler.has():in 操作符的捕捉器。
handler.deleteProperty():delete 操作符的捕捉器。
handler.getPrototypeOf():Object.getPrototypeOf 方法的捕捉器。
handler.setPrototypeOf():Object.setPrototypeOf 方法的捕捉器。
handler.isExtensible():Object.isExtensible 方法的捕捉器。
handler.preventExtensions():Object.preventExtensions 方法的捕捉器。
handler.getOwnPropertyDescriptor():Object.getOwnPropertyDescriptor 方法的捕捉器。
handler.defineProperty():Object.defineProperty 方法的捕捉器。
handler.ownKeys():Object.getOwnPropertyNames 方法和Object.getOwnPropertySymbols 方法的捕捉器。
handler.apply():函数调用操作的捕捉器。(函数也是一个对象,这里就对函数调用时进行监听)
handler.construct():new 操作符的捕捉器。(函数执行new操作符的时候进行监听)
利用Proxy和Reflect实现观察者模式

type obj = {
  get:() => void
  set:() => boolean
}
let list:Set<Function> = new Set()
let handler:obj = {
  get (){},
  set (target,key,value,receiver){
     let res  = Reflect.set(target,key,value,receiver)
     list.forEach(fn =>fn())
     return res
  }
}
let sutorun = (cb:Function) => {
  if(!list.has(cb)){
    list.add(cb)
  }
}
let observable = <T extends object>(par:T) => {
      return new Proxy(par,handler)
}

协变和逆变
协变:支持子类赋值给父类
逆变:支持父类赋值给子类
在这个过程中要保证类型安全
保证调用方参数类型的集合 >= 定义方的参数类型的集合,不管是协变还是逆变,都是为了达到一个目的,那就是【增加调用方参数类型拥有的属性和方法数量】,或者【减少定义方参数拥有的属性和数量】,来保证类型安全。
Set WeakSet
Set 类似一个数组,是对象,其中的值都是唯一的,Set本身是一个构造函数,用来生成 Set 数据结构。
其中操作方法有四个:
add(value):添加某个值,返回 Set 结构本身。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear(value):清除所有成员,没有返回值。

WeakSet类似一个数组,是对象,其中的值都是唯一的,WeakSet本身是一个构造函数,WeakSet的值必须都是对象并且是不可遍历的。
WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
其中操作方法有三个:
add(value):添加某个值,返回 WeakSet结构本身。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为WeakSet的成员。
Map WeakMap
Map 对象存有键值对,其中的键可以是任何数据类型(WeakMap不接受其他类型的值作为键名),Map 对象记得键的原始插入顺序,Map是一个构造函数,可以接受一个数组, 作为构造函数的参数。
Object传统上只能用字符串当作键。这给它的使用带来了很大的限制。
其中操作方法有五个:
set()方法再添加键/值对
get()获取 Map 对象中键的值
has()进行查询
delete()删除一个键/值对
clear()清除这个映射实例中的所有键/值对
WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名(而Map是任何类型都可)
WeakMap中的对象都是弱引用,即垃圾回收机制不考虑 WeakMap对该对象的引用,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakMap之中。
其中操作方法有四个:
set()方法再添加键/值对
get()获取 Map 对象中键的值
has()进行查询
delete()删除一个键/值对
Partial Pick
源码

//Partial 
type Partial<T> = {
    [P in keyof T]?: T[P];
}
//Pick
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
}

Record Readonly

//Readonly
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
  }
  //Record 
   type Record<K extends keyof any, T> = {
    [P in K]: T;
  }

keyof in含义

interface IPeople {
    name:string,
    age: number,
    sex: string,
  }
  type T = keyof IPeople
  //等于下面这种
  type T = "name" | "age" | "sex"

infer
infer只能在条件类型的 extends 子句中使用
infer得到的类型只能在true语句中使用

//infer只能是x
T extends U ? X : Y
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值