18、d.ts声明文件

  • 仅了解,需要用到时查文档
//todo  npm  声明文件可用npm 根据提示下载


// declare var 声明全局变量
// declare function 声明全局方法
// declare class 声明全局类
// declare enum 声明全局枚举类型
// declare namespace 声明(含有子属性的)全局对象
// interface 和 type 声明全局类型
/// <reference path="./14-泛型.ts"/> 三斜线指令


declare module 'express' {
  interface Router {
      get(path: string, cb: (req: any, res: any) => void): void
  }
  interface App {

      use(path: string, router: any): void
      listen(port: number, cb?: () => void): void
  }
  interface Express {
      (): App
      Router(): Router

  }
  const express: Express
  export default express
}

// 导入使用
import express from 'express';
// 对着声明时导出的接口
express.Router().get
express().use


19、Mixin混入

  • Object.getOwnPropertyNames()获取对象自身的属性,除去他继承来的属性,
  • prototype 获取原型
  • class C2 implements A1,A2 继承
//* Mixin 混入


//!   1.对象混入

interface name{
  name:string
}
interface name1{
  age:number
}


let na:name={
  name:'ASD'
}
let na1:name1={
  age:22
}

const nn=Object.assign(na,na1)
console.log(nn);  // { name: 'ASD', age: 22 }


//!  2.类的混入


 class A1 {
  type: boolean = false;
  changeType() {
      this.type = !this.type
  }
}


 class A2 {
  name: string = '张三';
  getName(): string {
      return this.name;
  }
}


//?1

class C2 implements A1,A2 {
    type:boolean=false
    changeType(): void {}
    name: string='张三';
    getName(): string {return this.name}
}
console.log(Object.getOwnPropertyNames(Object.create(A2).prototype)); // [ 'constructor', 'getName' ]


//?2
//获取A1,A2的原型到C2上  prototype原型


Mixins(C2, [A1, A2])
function Mixins(curCls:any,itemCls:any[]){
  itemCls.forEach(item=>{
    //Object.getOwnPropertyNames()可以获取对象自身的属性,除去他继承来的属性,
    Object.getOwnPropertyNames(item.prototype).forEach(name=>{
      curCls.prototype[name]=item.prototype[name]
    })
  })
}

20、Decorator装饰器的使用

  • //1.类装饰器 ClassDecorator
  • //2.属性装饰器 PropertyDecorator
  • //3.参数装饰器 ParameterDecorator
  • //4.方法装饰器 MethodDecorator PropertyDescriptor
  • 5.元数据 import ‘reflect-metadata’ 需要安装reflect-metadata使用暂不解释
//1.类装饰器    ClassDecorator
//2.属性装饰器  PropertyDecorator
//3.参数装饰器  ParameterDecorator
//4.方法装饰器  MethodDecorator  PropertyDescriptor
//5.元数据      import 'reflect-metadata'


//class类装饰器
const vv:ClassDecorator=(tag:Function)=>{
  tag.prototype.getTime=<T>(age:T):T=>{
    return age
  }
}

@vv
class a11{
  constructor(){
    
  }
}
//别名any 否则报错
console.log((new a11() as any).getTime('123'));


//装饰器工厂
const vvv=<T>(name?:T):ClassDecorator=>{
  // console.log(name);
  return (tag:Function)=>{
    tag.prototype.getTime=<T>(age:T):T=>{
      return age
    }
  }
}

@vvv('asd')
@vvv('asdasd')
@vvv()
class a22{
  constructor(){

  }
}
//别名any 否则报错
console.log((new a22() as any).getTime(1223));


//方法装饰器  属性装饰器
const met:MethodDecorator=(...args)=>{//方法
   console.log(args);
}
const pro:PropertyDecorator=(...args)=>{//属性
  console.log(args);
}
const par:ParameterDecorator=(...args)=>{//参数
  console.log(args);
}

class aaa2{
  @pro
  name:string = 'ss'
  constructor(){

  }
  @met
  getName(@par age:string ='123'):string{
    return age
  }
}

console.log(new aaa2());
//?方法
// [
//   {},
//   'getName',
//   {
//     value: [Function: getName],
//     writable: true,      是否可读写
//     enumerable: false,   是否可枚举
//     configurable: true   是否可配置
//   }
// ]

//?属性   [ {}, 'name', undefined ]
//       构造函数或实例 名字  

//?参数   [ {}, 'getName', 0 ]
//       构造函数或实例 名字  索引

21、-高级proxy拦截_Reflect元储存

/***
 *! Proxy 拦截器   
 *! Reflect 元存储
*/

let xxx={
  name:'yang',
  age:18
}

const namexxx = (Y:any)=>{
  return new Proxy(Y,{
    //拦截对象的读取
    get(target,key,receiver){//获取
       return Reflect.get(target,key,receiver)
    },  

    //拦截对象设置            
    set(target,key,value,receiver){//设置    
      return Reflect.set(target,key,value,receiver)
    },	  
    
    //'eyeCount' in targetObj // true 
    has(target,key){// 检查是否含有该属性
      return Reflect.has(target,key)
    },	          
    
    //拦截对象删除该属性
    deleteProperty(target,key){//删除该属性
       return Reflect.deleteProperty(target,key)
    },	     
    
    //获取原型
    getPrototypeOf(target){
      return Reflect.getPrototypeOf(target)
    },	 
    
    //设置原型 并删除原来的 
    setPrototypeOf(target,proto){
      //proto 原型方法
      return Reflect.setPrototypeOf(target,proto)
    },	        
    
    //不可扩展对象
    isExtensible(target){
      return Reflect.isExtensible(target)
    },	  
    
    /**
     * 判断该对象是否可扩展
    */
    preventExtensions(target){
      return Reflect.preventExtensions(target)
    },	     

    //返回对象属性的描述符   可读、枚举、配置1等
    getOwnPropertyDescriptor(target,key){
      return Reflect.getOwnPropertyDescriptor(target,key)
    },

    //修改对象属性描述属性配置
    defineProperty(target,key,proto){
      return Reflect.deleteProperty(target,key)
    },    
    
    //返回对象键的数组格式
    ownKeys(target){
      return Reflect.ownKeys(target)
    },	   
    
    //拦截函数的调用
    apply(target,Arg,Array){
      return Reflect.apply(target,Arg,Array)
    },	          
    
    //拦截new操作符
    construct(target,array){
      return Reflect.construct(target,array)
    },             
  })
}
namexxx(xxx)


//元储存
let Y={
  name:"人",
  age:'asd'
}

class qa{
  get(){
    console.log('asdasd');
  }
}

const aq={
name:'22',
get(){
  console.log(this.name);
}
}

let attributes ={ 
   value: '样',
   writable: true,
   enumerable: true,
   configurable: true
  }

/**
**    Reflect.get(Y,)	                         获取对象身上某个属性的值
**    Reflect.set()	                         在对象上设置属性
**    Reflect.has()	                         判断一个对象是否存在某个属性
**    Reflect.deleteProperty()	               删除对象上的属性
**    Reflect.getPrototypeOf()	               获取指定对象原型的函数
**    Reflect.setPrototypeOf()	               设置或改变对象原型的函数
**    Reflect.isExtensible()	                 判断一个对象是否可扩展 (即是否能够添加新的属性)
**    Reflect.preventExtensions()	           阻止新属性添加到对象
**    Reflect.getOwnPropertyDescriptor()	     获取给定属性的属性描述符
**    Reflect.defineProperty()          	     定义或修改一个对象的属性
**    Reflect.ownKeys()	                     返回由目标对象自身的属性键组成的数组
**    Reflect.apply()	                       对一个函数进行调用操作,同时可以传入一个数组作为调用参数
**    Reflect.construct()	                   对构造函数进行 new操作,实现创建类的实例
 * **/

//获取
Reflect.get(Y,'age')	                 

//设置
Reflect.set(Y,'age','111')	   
console.log(Reflect.set(Y,'age','111')	);//true
              
//检查是否含有该属性
Reflect.has(Y,'name')	 
console.log(Reflect.has(Y,'name')	);//true

//删除该属性
Reflect.deleteProperty(Y,'age')	
console.log(Reflect.deleteProperty(Y,'age')	);//true

//获取原型
Reflect.getPrototypeOf(Y)

//设置原型 并删除原来的   
Reflect.setPrototypeOf(Y,qa)	 
console.log((Y as any).prototype);  //{}

//不可扩展对象
Reflect.isExtensible(Y)	           

//判断该对象是否可扩展
Reflect.preventExtensions(Y)	     

//返回对象属性的描述符   可读、枚举、配置1等
Reflect.getOwnPropertyDescriptor(Y,'name')
console.log(Reflect.getOwnPropertyDescriptor(Y,'name'));//{ value: '人', writable: true, enumerable: true, configurable: true }

//修改对象属性描述属性配置
Reflect.defineProperty(Y,'name',attributes)
console.log(Y);   //attributes{ value: '人', writable: true, enumerable: true, configurable: true }
         
//返回对象键的数组格式
Reflect.ownKeys(Y)	 

//对一个函数进行调用操作,同时可以传入一个数组作为
Reflect.apply(aq.get,aq,[1,2,3])	                 
console.log( Reflect.apply(aq.get,aq, [1,2,3]));

//
function Person12 (name:string, hobby:string){
console.log(`${name}喜欢${hobby}`);
return `${name}喜欢${hobby}`
}

// 对构造函数进行 new操作,实现创建类的实例
const person = Reflect.construct(Person12, ['一碗周','coding'],Person12)


/** 
*!    总结
*!    Reflect对象提供哪些静态方法,都是可以通过另一种方式来完成的,那为什么还要提供一个Reflect对象呢?
*!    
*!    这是因为前面的那十三种操作,可能来自不同的对象里面的方法,有全局的、有Object的、有Function的,但是提供了Reflect对象之后就将前面所有的操作统一到了一个对象下面 ,也统一了操作方式 。

22、-高级写法Partial-Pick

//*进阶用法 Partial   Pick
/**
 * Make all properties in T optional
 * 将T中的所有属性设置为可选
 * 与ts自带的Partial冲突才加的Partialed,可直接使用Partial
 */
  type Partialed<T> = {
    [P in keyof T]?: T[P];
};

type PersonS = {
  name:string,
  text:string
  age:number
}

/**
 * 转换后全部属性为可选 keyof取出属性变成联合类型  ,
 * in类似for in遍历   ,
 * ?变为可选,
 * T[P]索引访问,
 **/
type p =Partialed<PersonS>

//!
/**
 * From T, pick a set of properties whose keys are in the union K,
 * 从类型定义T的属性中,选取指定一组属性,返回一个新的类型定义。
 * 返回"text" | "age" 并组成新类型定义
 * 与ts自带的Pick冲突才加的Picked,可直接使用Pick
 */
type Picked<T, K extends keyof T> = {
  [P in K]: T[P];
};

type Ex = "text" | "age"

type C =Picked<PersonS,Ex>

23、Readonly只读_Record套对象

//  Readonly 只读  Record 套一层对象

/**
 * !Readonly
 * Make all properties in T optional
 * 将T中的所有属性设置为只读
 * 与ts自带的Partial冲突才加的Partialeds,可直接使用Partial
 */
  type Partialeds<T> = {
    readonly [P in keyof T]: T[P];
};

type Personed = {
  name:string,
  text:string
  age:number
}

/**
 * 转换后全部属性为只读 keyof取出属性变成再声明为只读,
 * in类似for in遍历   ,
 * readonly变为只读,
 * T[P]索引访问,
 **/
type ps =Partialeds<Personed>



/**
 * ! Record ,
 * * 作用:返回一个自定义的键包裹类型定义
 * 0:{
 *   name:"",
 *   text:'',
 *   age:1
 * }
 * 限制键值对
 **/ 

 type Records<K extends keyof any, T>={
    [P in K]:T
 }
 
 type sa=Records<0,Personed>
 
 let ssss:sa={
  0:{
    name:"",
    text:'',
    age:1
  }
 }

24、高阶写法Infer占位符

// infer的作用 新增的关键字-用于占位符
// 需求:定义一个类型 如果是数组类型 就返回 数组元素的类型 否则 就传入什么类型 就返回什么类型
// 01:简单的定义 数组
type TYPE<T> = T extends Array<any> ? T[number] : T;
type AAAA = TYPE<string[]>;
let aaaa: AAAA = "111";

type BBBB = TYPE<boolean>;
let bbbb: BBBB = true;

// 02:使用infer U做占位符
type TYPE2<T> = T extends Array<infer U> ? U : T;
type AAAA2 = TYPE2<(string | number)[]>;
let aaaa2: AAAA2 = 1;

type BBBB2 = TYPE2<boolean>;
let bbbb2: BBBB2 = true;

// 03:使用infer U做占位符 - 联合类型
type TYPE3<T> = T extends Array<infer U> ? U : never;
type TTTT = [number, string];
type uni = TYPE3<TTTT>; // type uni = string | number
type uni2 = TYPE3<boolean>; // type uni2 = never

// 04:使用infer U做占位符 - 提取数组之中的某一项元素
type Arr = ["a", "b", "c"];
// 04-1 提取第一项
type First<T extends any[]> = T extends [infer one, infer two, ...any[]]
  ? one // one => type a = "a"; two type a = "b";
  : [];
type a = First<Arr>; // type a = "a"

// 04-2 提取最后一项
type Last<T extends any[]> = T extends [...any[], infer Last] ? Last : [];
type b = Last<Arr>; // type b = "c"

// 04-3 删除最后面一项
type Pop<T extends any[]> = T extends [...infer Rest, infer Last] ? Rest : [];
type c = Pop<Arr>; // type c = ["a", "b"]

// 04-3 删除最前面一项
type Shif<T extends any[]> = T extends [infer Last, ...infer Rest] ? Rest : [];
type d = Shif<Arr>; // type d =  ["b", "c"]

// 05:使用infer U做占位符 - infer递归 ( 翻转数组 )
type Arr2 = [1, 2, 3, 4];
type ReverArr<T extends any[]> = T extends [infer First, ...infer Rest] ? [...ReverArr<Rest>,First] : T;
type ArrRever = ReverArr<Arr2> // type ArrRever = [4, 3, 2, 1]

25、Inter实现提取类型和倒叙递归

//类型提取 Infer 

type Arrs = ['a','b','c']
 /**
  * 返回头或尾
 */
type First<T extends any[]> =  T extends [...any[],infer First] ? First : []  

/** 
 * 返回删除头或尾后的数组
 * unknown声明
*/
type Firsts<T extends any[]> =  T extends [...infer First,unknown] ? First : []
type a = First<Arrs>
type aa = Firsts<Arrs>


//Infer  递归用法

//*倒叙
type Arr = [1, 2, 3, 4]
 
/**
 * [infer First, ...infer rest]  [...ReveArr<rest>, First]
 * 将第一个First放在后面,反复调用每次会自动减少
*/
type ReveArr<T extends any[]> = T extends [infer First, ...infer rest] ?[...ReveArr<rest>, First] : T
 
type Res = ReveArr<Arr>  // [4, 3, 2, 1]

26、object、Object、{}的区别

//object、Object 以及{}的区别用法

/**
 * !  object 是一个表示非原始类型的类型。它可以包括任何非原始类型,如数组、函数、对象等。
 * !  Object 是 JavaScript 中的内置对象,它是所有对象的基类。
 * !  {} 是一种简写形式,表示一个空对象。在 TypeScript 中,{} 可以用作类型注解,表示一个空对象类型。
*/

/**
 * * object 表示对象类型  
 * */ 
let a1:object={}

/**
 * *Object是JS的内置对象,表示所有对象的原型顶层 
*/
let a2:Object= Object


/**
 * *{}空对象,类型和Object一样在ts里面 没有Object的方法属性
*/
let a3={}

27、localStorage封装

let a = new Date().toLocaleString()

interface time{
   outtme:string
}


type Key=string

interface Result { //返回值类型
  message: string,
  value: object
}

interface setvalue{
  set:<T>(key:Key,value:T,time?:number)=>void
  get:<T>(key:Key)=>void
  remove:(key:Key)=>void
  clear:()=>void
}
interface vas{
    value:Object
    time?:number
}
enum out{
  yes,
  no
}
class Storages implements setvalue{
   get(key:Key){
      if(key){
         let keys= JSON.parse(localStorage.getItem(key) as string)
         console.log();
         if(new Date().getTime() / 1000 < keys.value){
           return keys
         }else{
          return{
            message:`已过期,请重新设置`,
          }
         }
        
      }
   } 
   set(key:Key,value:any,time?:out|number){
      if(value!=undefined && value!=null ){
         let va ={
          value:value,
          time:(typeof time=='number'?time:0) +Number(new Date().getTime()) / 1000  //毫秒转秒
         }
         if(time!=0){
            
            localStorage.setItem(key,JSON.stringify(va))
            return{
              message:`过期设置`,
              value:value
            }
         }else if(time==0){
            localStorage.setItem(key,JSON.stringify(va))
            return{
              message:`永不过期设置`,
              value:value
            }
         }
      }else{
         return {
           message:`设置${key}错误,是个空值或或没声明的值`
         }
      }
   }
   remove(key:Key){
     localStorage.removeItem(key)
   }
   clear(){
     localStorage.clear()
   }
}
const times =new Storages()
console.log(times.set('start',123,21));
console.log(times.get('start'));

28、协变-逆变-双向协变(赋值操作)

//!协变

//当属性多的一个包含属性少的变量时,可以产生协变  赋值操作

  //*多赋少
  
interface A {
  name:string
}

interface B {
  name:string
  age:number
  sex:string
}

let a:A = {
  name:"老墨我想吃鱼了",
}

let b:B = {
  name:"老墨我不想吃鱼",
  age:33,
  sex:"女"
}

a = b

console.log(a);
console.log(b);

//!逆变

//函数上 函数赋值 少赋多

let fna = (params:A) => {
 
}
let fnb = (params:B) => {
    
}
 
// fna = fnb //错误
 
fnb = fna //正确


//!双向协变


//设置tsconfig.json   属性strictFunctionTypes=false,可进行双向赋值操作 双向协变

29、Set_Map和WeakSet_WeakMap(es6方法和弱引用)

//!weakMap,weakSet,set,map

//1.set 集合

//add(value):添加某个值,返回 Set 结构本身。
//
//delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
//
//has(value):返回一个布尔值,表示该值是否为 Set 的成员。
//
//clear():清除所有成员,无返回值。
//
//size : 返回set数据结构的数据长度 

let a= new Set()
a.add('sasd')
//去重    配合扩展运算符可以去重
let b= [...new Set(['asdsa','asd'])]


//2.map 它类似于对象,也是键值对的集合

let c= new Map()

caches.delete('asd')
c.has('s')//查询是否有's'
c.clear()
c.get('ad')
c.set('asd','asd')
c.size



//WeakSet 和 WeakMap  当不引用是
//WeakSet的成员只能是对象,WeakMap只接受对象(null除外)作为键名       
//不计入垃圾回收机制    
//没有遍历操作,没有size属性,没有clear方法
//不需要时会自动GC回收
//可以放其他东西,dom 函数等, 不用回自动回收掉

let obj:any = {name:'小满zs'} //1
let aahph:any = obj //2
let wmap:WeakMap<object,string> = new WeakMap()
 
wmap.set(obj,'爱安徽潘慧') //2 他的键是弱引用不会计数的
 
obj = null // -1
aahph = null;//-1
//v8 GC 不稳定 最少200ms
 
setTimeout(()=>{
    console.log(wmap)
},500)

总结

11-27 13:58