ts学习 基本篇(类型) 01 - ts基本类型 
类型 
例子 
描述 
 
 
number 
1, -33, 2.5 
任意数字 
 
string 
‘hi’, “hi”, 
任意字符串 
 
boolean 
true、false 
布尔值true或false 
 
字面量 
其本身 
限制变量的值就是该字面量的值 
 
any 
* 
任意类型 
 
unknown 
* 
类型安全的any 
 
void 
空值(undefined) 
没有值(或undefined) 
 
never 
没有值 
不能是任何值 
 
object 
{name:’孙悟空’} 
任意的JS对象 
 
array 
[1,2,3] 
任意JS数组 
 
tuple 
[4,5] 
元素,TS新增类型,固定长度数组 
 
enum 
enum{A, B} 
枚举,TS中新增类型 
 
number类型
 
let  decimal :number  = 6 ; let  hex :number  = 0xf00d  let  binary :number  = 0b1010  let  octal :number  = 0o744  let  big :number  = 100n  
let  isDone :boolean  = true let  isDone1 :boolean  = false 
let  color :string  = "blue"  let  fullName :string  = `Bob ${color} ` 
字面量
使用具体的值来指定变量的类型或取值范围
let  color :'red' |'blue' |'black' let  num :1 |2 |3 |4 |5 
 
any类型
 
let  a :any  = true a = 1  a = '1'  
unknown类型
let  notSure :unknown  = 4 notSure = 'hello'  
void类型
let  unusable :void  = undefined 
never类型
function  error (message:string  ):never {    throw  new  Error (message) } 
object类型
let  obj :object  = {name :"pan" }
array类型
let  list :number [] = [1 ,2 ,3 ]let  list1 :Array <number > = [1 ,2 ,3 ]
tuple类型
let  x :[string ,number ] = ['hello' ,1 ]
enum类型
enum  Sex {    mail = 1 ,     femail = 0  } const  sex :Sex  = Sex .mail enum  FangXiang {    top,       right = 3 ,      bottom,        left    } console .log (FangXiang .right ) 
02 - 类型别名 type 定义 用于一些较长的类型,可以使用type来进行类型别名,避免代码定义类型冗余
type  Num  = 1  | 2  | 3  | 4 let  num1 :Num  = 1 num1 = 2  
03 - interface 接口 定义 interface 和type 一样可以定义类型别名
interface  Num  {    name :string ,     age :number  } const  formData :Num  = {    name :'pan' ,     age :18  } 
04 - type和interface的区别 
05 - 类型断言 当自动识别的类型不满足自己的需要时,可以使用类型断言来得到更准确的自己需要的类型
const  canvasRrow = document .getElementById ("main_canvas" )const  canvasRrow1 = document .getElementById ("main_canvas" ) as  HtmlCanvasElement const  canvasRrow1 = <HtmlCanvasElement >document .getElementById ("main_canvas" ) 
06 - 文字类型 文字类型使用于对数据进行只读操作,不能进行修改
const  obj = {    url :"https://www.baidu.com" ,     method :"GET" , } as  const  function  request (url:string ,method:"GET"  | "POST"  | "PUT"  ) {     } request (obj.url ,obj.method )
07 - bigInt和symbol const  a :bigint  = BigInt (100 )const  b :bigint  = 100n const  firstName = Symbol ('name' )const  secondName = Symbol ('name' )
08 - typeof类型守卫 function  sum (n:string  | number ,input:string  ){    if (typeof  n === 'number' ){         return  Array (n + 1 ).join (' ' ) + input     }else {         return  n + input     } } console .log (sum ("你好" ,'hello' ));
09 - 真值缩小 遇到 条件、&&、||、if语句、布尔否定(!)会产生真值缩小
function  printAll (strs:string  | string [] | null  ): void {              if (strs && typeof  strs === 'object' ){         for (let  str of  strs){             console .log (str);         }     }else  if (typeof  strs === 'string' ){         console .log (strs);              }else {              } } 
10 - 等值缩小 遇到  === 、!== 、== 、!= 的时候会产生等值缩小
function  example  (x :string  | number  ,y :string  | boolean ){    if (x === y){         x = x.toUpperCase ()         y = y.toLowerCase ()         console .log (x,y);     }else {         console .log (x);         console .log (y);     } } example ("hello" ,"ello" );function  example  (x :string  | number  ,y :string  | boolean ){    if (x === y){         x = x.toUpperCase ()         y = y.toLowerCase ()         console .log (x,y);     }else {         console .log (x);         console .log (y);     } } example ("hello" ,"ello" );function  printAll (strs:string  | string [] | null  ){    if (strs !== null ){         if (typeof  strs === 'object' ){             for (const  x of  strs){                 console .log (x)             }         }else  if (typeof  strs === 'string' ){             console .log (strs)         }     } } 
11 - in 操作符缩小 使用in操作符判断是否包含有
type  Fish  = { swim : () =>  void  };type  Bird  = { fly : () =>  void  };type  man = { swim?: () =>  void , fly?: () =>  void }function  move (animal: Fish | Bird | man ) {  if  ('swim'  in  animal) {     return  (animal as  Fish ).swim ();   }   return  (animal as  Bird ).fly (); } 
12 - instanceof 操作符缩小 使用instanceof操作符来进行判断 是否在原型链上来进行判断操作
function  printAll  (x :string  | Date ){    if  (x instanceof  Date ){         console .log (x.toUTCString ());     } else  {         console .log (x.toUpperCase ());     } } 
13 - 分配缩小 使用三目表达式来进行分配缩小
let  x = Math .random () < 0.5 ?10 :'' x = 1  console .log (x);x = 'hello'  console .log (x);
14 - 类型谓词 在函数返回值时进行判断是否为真还是假进行对应的返回类型
type  Fish  = {    name :string ,     swim :()=> void  } type  Bird  = {    name :string ,     fly :()=> void  } function  isFish (pet:Fish|Bird ):pet is Fish {    return  (pet as  Fish ).swim  !== undefined  } function  getSmallPet (Fish |Bird {    let  x :Fish  = {         name :'fish' ,         swim :()=> {}     }     let  y :Bird  = {         name :'bird' ,         fly :()=> {}     }     return  false ? y : x } const  pet = getSmallPet ()if (isFish (pet)){    pet.swim ()     console .log ('真' );      }else {     pet.fly ()     console .log ("假" );      } 
15 - unions(联合类型) interface  Square  {    type : 'square' ;     sideLength :number  } interface  Rectangle  {    type : 'rectangle' ;     radius :number  } type  Shape  = Square  | Rectangle ;function  getArea (shape: Shape ){    switch (shape.type ){         case  'square' :             return  shape.sideLength  ** 2          case  'rectangle' :             return  Math .PI  * shape.radius  ** 2      } } 
16 - never 类型 使用范围,穷进行检查,来判断拓展接口进行错误提示
interface  Square  {    type : 'square' ;     sideLength :number  } interface  Rectangle  {    type : 'rectangle' ;     radius :number  } interface  sanjiao {    type : 'sanjiao'      sideLength :number  } type  Shape  = Square  | Rectangle  | sanjiao;function  getArea (shape: Shape ){    switch (shape.type ){         case  'square' :             return  shape.sideLength  ** 2          case  'rectangle' :             return  Math .PI  * shape.radius  ** 2          case  'sanjiao' :             return  shape.sideLength  ** 2          default :             const  _qiong :never  = shape;              return  _qiong;     } } 
基本篇(函数) 01 - 函数类型表达式 定义函数类型
type  GrandeFunction  = (n:string  )=> void function  handleFunction (fn:GrandeFunction ){    fn ('hello world' ) } function  helloWorld (n:string  ){    console .log (n);     console .log ('hello world' ) } handleFunction (helloWorld)
02 - 调用签名 其实就是定义了一个函数,在函数身上定义了一个方法
type  dirceFunction = {    dirce :string ,     (str :string ):boolean  } function  handleDirce (fn:dirceFunction ){    console .log (fn.dirce  + 'hello' ); } function  handle1 (    console .log ('handle1' );     return  true ; } handle1.dirce  = '我的'  handleDirce (handle1)
03 - 构造签名 其实构造签名就是定义了一个类。
class  Ctor  {    n :string      constructor (n:string  ){         this .n  = n     } } type  constroller = {    new  (n :string ):Ctor  } function  handleConstroller (fn:constroller ){    const  fn1 = new  fn ('hello' )     console .log (fn1.n ); } handleConstroller (Ctor )interface  DateFunc {    new  (n :string ):Date      (s :number ):string  } function  handleFunc (func:DateFunc ){    const  a = new  func ("2024-1-8" )     const  b = func (100 ) } handleFunc (Date )
04 - 泛型函数 04 - 1- 类型推断 使用场景,使用前不知道会使用什么类型,在使用时,类型之间想要产生关联就使用泛型。
function  handleString<T>(arr :T[]):T{    return  arr[0 ] } handleString ([1 ,2 ,3 ])function  map<I,O>(arr :I[],func :(item:I )=> O):O[]{    return  arr.map (func) } const  parsed = map (["1" ,"2" ,"3" ],(item )=> parseInt (item))
04 - 2 - 限制条件 使用extends来继承祖代值,来进行限制类型
function  longest<T extends  {length :number }>(a :T,b :T):T{    if (a.length >b.length ){         return  a     }else {         return  b     } } const  res1 = longest ([1 ,2 ,3 ],[1 ,2 ])const  res2 = longest ('abc' ,'ab' )const  res3 = longest (100 ,10 ) 
04 -3 - 指定类型参数 当泛型需要不只一种可能性参数时使用
function  handleTest<T>(a :T[],b :T[]):T[]{    return  a.concat (b) } handleTest<string |number >([1 ,2 ,3 ],["1" ,"2" ,"3" ]) 
05 - 函数可选值 函数可选值为函数参数上加一个?来判断参数可选
function  handleTest (n?:number  ):undefined  |string {     if  (!(n === undefined )) {         return  n.toFixed (3 )     }else {         return  undefined      } } console .log (handleTest (10 ));console .log (handleTest ());
06 - 回调中的可选参数 在创建回调函数中,不要写可选值,避免错误出现!
function  handleTest (arr:any [],callback:(value:any ,index?:number )=>void  ){    for (let  i=0 ;i<arr.length ;i++){         callback (arr[i])     } } handleTest ([1 ,2 ,3 ],(value,index )=> {    console .log (index?.toFixed ()) }) 
07 - 函数重载 07 - 1 - 函数重载函数情况 使函数有多种传参方式,可以根据自己的参数要求来
注意:在写函数重载时,最后一个重载为前面所有函数参数的一个总和
function  makeDate (timemap:number  ):Date function  makeDate (month:number ,day:number ,year:number  ):Date function  makeDate (mOrTimestamp:number ,d?:number ,y?:number  ):Date {    if (d!== undefined  && y!== undefined ){         return  new  Date (y,mOrTimestamp,d)     }else {         return  new  Date (mOrTimestamp)     } } const  res1 = makeDate (100 )const  res2 = makeDate (100 ,1 ) const  res3 = makeDate (100 ,1 ,2020 )
注意:前两个函数叫做函数重载,叫做重载签名,后面一个叫做实现签名。实现签名要兼容前面的重载签名情况。
function  handleTest (x:string ,y:number  ):string function  handleTest (x:number ,y:boolean ,z:string [] ):number function  handleTest (x:string  |number ,y:number  | boolean ,z?:string [] ):string  | number  {    if (typeof  x === 'string' ){         return  'string'      }else {         return  10      } } 
07 - 2 - 函数重载 - this interface  User  {    admin :boolean  } interface  DB{    filterUser (filters :(this :User boolean ):User [] } const  db :DB ={    filterUser (filters:(this :User)=>boolean  ){         let  user1 :User  = {             admin :true          }         let  user2 :User  = {             admin :false          }         return  [user1,user2]     } } const  adminUsers = db.filterUser (function (this :User    return  this .admin  }) console .log (adminUsers);
08 - 展开运算符 08 -1- 展开运算符-形参展开 function  handleBei (n:number ,...res:number [] ):number []{    return  res.map (v => } handleBei (5 ,1 ,2 ,3 ,4 )
08 -2- 展开运算符-实参展开 const  arr = [8 ,5 ] as  const const  angle = Math .atan2 (...arr)type  Arr  = [number ,number ]const  arr1 :Arr  = [5 ,6 ]const  angle1 = Math .atan2 (...arr1)
09 - 参数解构(定义类型) interface  ABC{    a :number      b :number      c :number  } function  sum ({a,b,c}:ABC ){    return  a+b+c; } sum ({a :1 ,b :2 ,c :3 });
基础篇(对象) 01 - 对象类型 function  handleObj0 (person: { name: string , age: number  } ){    return  person.name  } interface  Person1  {    name : string ,     age : number  } function  handleObj1 (person: Person1 ){    return  person.name  } type  Person2  = {    name : string ,     age : number  } function  handleObj (person: Person2 ){    return  person.name  } 
02 - 可选属性 interface  Person  {    name :string ,     age?:number      desc?:string  } function  showPerson ({name,age=0 ,desc='' }:Person ){    console .log (name,age,desc); } showPerson ({name :'张三' ,age :20 })showPerson ({name :'张三' ,age :20 ,desc :'学生' })
03 - 只读属性 注意:只读属性readonly只针对当前的属性进行只读操作,并不是对其内部有其内部的限制
interface  ReadonlyPerson  {    readonly  person :{         name :string          age :number      } } let  persons :ReadonlyPerson  = {    person :{         name :"张三" ,         age :18      } } persons.person .age  = 18   persons.person  = {name :"李四" ,age :20 }  
interface  ReadonlyPerson  {    readonly  name :string      readonly  age :number  } interface  Person  {    name :string      age :number  } let  person :Person  = {name :'张三' ,age :18 }let  readonlyPerson :ReadonlyPerson  = personperson.age ++ console .log (readonlyPerson.age );
04 - 索引签名 interface  Person1  {    [index :number ]:string ; } let  person :Person1  = ['1' ,'2' ,'3' ]let  person1 :Person1  = {0 :'1' ,1 :'2' ,2 :'3' }interface  Person2  {    [prop :string ]:string  | number ;     name :string      length :number  } let  person2 :Person2  = {    name :"张三" ,     length :18 ,     age :18 ,     desc :''  } 
05 - 拓展类型 interface  StudentBase  {    name :string      age :number  } interface  Student  extends  StudentBase  {    grade :string  } const  student1 :Student  = {    name :"张三" ,     age :18 ,     grade :"一年级"  } interface  Circle  {    radius :number  } interface  Color  {    color :string  } interface  CircleColor  extends  Circle ,Color  {    name :string  } let  circleColor :CircleColor  = {    name :'circle' ,     radius :10 ,     color :'red'  } 
06 - 交叉类型 interface  Circle  {    radius :number  } interface  Color  {    color :string  } type  CircleWithColor  = Circle  & Color function  dorwCircle (dorw:CircleWithColor ){    console .log (dorw.color );     console .log (dorw.radius ); } dorwCircle ({radius :1 ,color :"blue" })
07 - 处理冲突(interface、type) interface  Person  {    name :string  } interface  Person  {    age :number  } const  person :Person  = {    name :"张三" ,     age :30  } type  Person1  = {    name :string  } type  Person1  = {    age :number  } 
08 - 泛型对象类型 使用泛型来对对象进行泛型约束
interface  Person <T>{    contens :T } const  res :Person <string > = {    contens :"hello"  } type  Person1 <T> = {    contens :T } const  res1 :Person1 <string > = {    contens :"hello"  } type  perOrNull<T> = T | null type  perOrMany<T> = T | T[]type  perOrManyOrNull<T> = perOrMany<T> & perOrNull<T>type  perOrManyOrNull<T> = perOrNull<perOrMany<T>>
基础篇(泛型) 01 - helloWord开始篇章 function  putUser<T>(a :T):T{    return  a } const  a = putUser<number >(1 )const  b = putUser (1 )
02 - 使用通用类型变量 function  handleloading<T>(arr :T[]):T[]{    console .log (arr.length );     return  arr } handleloading<number >([1 ,2 ,3 ]) 
03 - 泛型类型 泛型类型就相当于给接口定义了泛型
interface  GenericIdentityFn <T>{    (arg :T):T } function  handleloading<T>(arr :T):T{    return  arr } 这几种都等价 let  myIdentity :GenericIdentityFn <string >=handleloading
04 - 泛型类 class  Person <T>{    num : T;     add :(x:T,y:T )=> T } let  p = new  Person <number >();p.num  = 123 ; p.add  = (a,b )=> a+b; 
05 - 泛型约束 使用extends来进行对泛型进行约束
interface  lengthwise {    length : number ; } function  printLength<T extends  lengthwise>(x : T){    console .log (x.length ); } printLength ('10' )
06 - 在泛型约束中使用类型参数 这个keyof 表示K必须是在T的泛型中存在的,对应的是key值
function  handleTest<T,K extends  keyof T>(arr :T,key :K):T[K] {    return  arr[key]; } var  obj = {a : 1 , b : 2 , c : 3 };console .log (handleTest (obj, "a" )); console .log (handleTest (obj, "b" )); console .log (handleTest (obj, "c" )); console .log (handleTest (obj, "d" )); 
07 - 在泛型中使用类类型 class  BeeKeeper  {    hasMask : boolean  = true  } class  Zookeeper  {    nametag : string  = "Mikle"  } class  Animal  {    numLegs : number  = 4  } class  Bee  extends  Animal  {    keeper : BeeKeeper  = new  BeeKeeper () } class  Lion  extends  Animal  {    keeper : Zookeeper  = new  Zookeeper () } function  create<T extends  Animal >(c :new  ()=>T):T{    return  new  c () } create (Lion )create (Bee )create (Animal )create (Zookeeper ) create (BeeKeeper ) 
基础篇(操作约束) 01 - keyof类型操作符 注意:使用keyof操作索引签名时候,会默认存在一个隐式的number类型
type  Point0  = {    x :number ,     y :number  } type  A = keyof Point0  const  a :A = 'x' const  b :A = 'y' type  Point1  = {    [n :number ]:unknown  } type  B = keyof Point1  const  c :B = 1 const  d :B = 2 type  Point2  = {    [n :string ]:unknown  } type  C = keyof Point2  const  e :C = '1' const  f :C = 1 
02 - typeof 类型操作符 let  a :number  = 1 let  b :typeof  a = 2 function  fn (    return  {         x :1 ,         y :'1'      } } type  Fn  = typeof  fnconst  fn1 :Fn  = ()=> {    return  {         x : 2312 ,         y : '123'      } } 
03 - 索引访问类型  type  Person  = {     name : string ;     age : number ;     isStudent : boolean ; } type  PersonChild  = Person [keyof Person ]type  NameOrAgePerson  = 'age'  | 'name' type  I0  = Person [NameOrAgePerson ]const  array = [    {name : '张三' , age : 18 , isStudent : true },     {name : '李四' , age : 20 , isStudent : false },     {name : '王五' , age : 22 , isStudent : true }, ] type  arraytype1 = typeof  array[number ]type  arraytype2 = typeof  array[number ]['age' ]
04 - 条件类型 interface  Fish  {    siwm :boolean  } interface  Bird  {    fly :string  } type  HandleTest <T> = T extends  {siwm :true } ? string  : number type  HandleTest2  = HandleTest <Fish > type  HandleTest3  = HandleTest <Bird > 
05 - 条件类型约束 interface  Fish  {    siwm :boolean  } interface  Bird  {    fly :string  } type  HandleTest0 <T extends  {siwm :unknown }> = T extends  {siwm :true } ? string  : number type  HandleTest2  = HandleTest0 <Fish >type  HandleTest3  = HandleTest0 <Bird > type  HandleTest1 <T> = T extends  any [] ? T[number ] : Ttype  HandleTest4  = HandleTest1 <string []> type  HandleTest5  = HandleTest1 <number []> type  HandleTest6  = HandleTest1 <number > 
06 - 在条件类型中进行推理 type  HandleTest0 <T> = T extends  (...agrs : never []) => infer Return   ? Return    : never ; type  Num  = HandleTest0 <()=> number > type  Str  = HandleTest0 <(x:string  )=> string > type  Bools  = HandleTest0 <(a:boolean ,b:boolean  )=> boolean > function  handleTest (x: number  ): string ;function  handleTest (x: string  ): number ;function  handleTest (x: number  | string  ):string  | number function  handleTest (x: number  | string  ): string  | number  {  return  Math .random () > 0.5  ? "hello"  : 1 ; } type  Test  = HandleTest0 <typeof  handleTest>;
07 - 分布式条件类型 对于单个类型进行依次判断
type  handleTest1<T> = T extends  any ?T[]:never type  handleTest2<T> = [T] extends  [any ]?T[]:never type  A = handleTest1<string  | number  | boolean >type  B = handleTest2<string  | number  | boolean >
基础篇(类) 01 - 类成员 类成员分为:类属性、readonly、构造器、方法、Getters/Setters 、索引签名
02- 类属性 class  Person  {    x :string      y :number      constructor (x:string ,y:number  ){         this .x  = x         this .y  = y     } } let  person = new  Person ("1" ,1 )
03 - readonly属性 class  Person  {    readonly  x :string      constructor (x:string  ){         this .x  = x     } } let  person = new  Person ('你好' )console .log (person.x );person.x  = '你好啊'   
04 - 构造器 class  Base  {    age :number      constructor (age:number  ) {         this .age  = age     } } class  Person  extends  Base  {    name :string      constructor (name:string ,age:number  ){         super (age)         this .name  = name     } } const  person = new  Person ("张三" ,18 )
05 - 方法 class  Base  {    age :number      constructor (age:number  ) {         this .age  = age     }     getAge (         return  this .age      } } const  person = new  Base (18 )
06 - getters和setters访问器 class  Base  {    _age :number  = 0      get  age ():number {         return  this ._age      }     set  age (value:number  | string  | boolean  ){         const  num = Number (value)         if (!Number .isFinite (num)){             this ._age  = 0              return          }         this ._age  = num     } } const  person = new  Base ()person.age  = '20'  console .log (person.age )person.age  = '20a'  console .log (person.age );
07 - 索引签名 class  Person  {         [k :string ]:string  | ((s?:string  )=> void )     name :string  = 'pansida'      getName (         console .log (this .name );              } } const  person = new  Person ()person.getName () 
08 - 继承 implements子句 这个implements就是相当于定义class实体类时可以使用implements子句来进行给实体类定义类型
interface  Person  {    name :string      fn :(n:string  )=> void  } class  HandleTest  implements  Person {    name : string  = 'pan'      fn (n:string  | number  ){         if (typeof  n === 'string' ){             console .log (n.length )         }else {             console .log (n)         }     } } 
09 - 继承 extends子句 class  A  {    he (         console .log ('A' );     } } class  B  extends  A  {    worf (times:number  ){         for  (let  index = 0 ; index < times; index++) {             console .log ('B' );         }     } } const  c = new  B ();c.he () c.worf (5 ); 
10 - 重写方法 class  A  {    he (         console .log ('A' );     } } class  B  extends  A  {    he (times?:string  ){         if (times === undefined ){             super .he ();         }else {             console .log ('B:' ,times);                      }     } } const  c = new  B ();c.he () c.he ('render' ); 
11 - 初始化顺序 注意(初始化顺序) :
基类的字段被初始化 
基类构造函数运行 
派生类的字段被初始化 
派生类构造函数运行 
 
class  A  {    name = 'A'      constructor (         console .log ('A中:' ,this .name );              } } class  B  extends  A  {    name = 'B'      constructor (         super ()         console .log ('B中:' ,this .name );              } } const  c = new  B ();
12 - 继承内置类型 class  MyError  extends  Error  {    constructor (message:string  ){         super (message)         this .message  = message;                               }     SayHello (){         console .log (this .message );               } } const  myerror = new  MyError ("Hello" );myerror.SayHello (); 
13 - 成员的可见性-public class  Person  {         public  greet (         console .log ("hi!" );              } } class  Children  extends  Person  {    constructor (         super ()                  this .greet ()     } } const  child = new  Children ()child.greet ()  
14 - 成员的可见性-protected class  Person  {    public  name = 'pan'          protected  SaiHello (){     console .log ("Hello" );         }  } class  Children  extends  Person  {    constructor (         super ()                  this .SaiHello ()     } } const  child = new  Children ()class  M  {    protected  name = 'pan:M'  } class  N  extends  M  {    public  name = 'pan:N'  } const  test = new  N ()console .log (test.name );
15 - 成员的可见性 - privide class  Person  {    private  name = 'pan'          public  SaiHello (){     console .log (this .name );    }  } class  Children  extends  Person  {    constructor (         super ()         this .SaiHello ()              } } const  child = new  Children ()class  A  {    private  name = 'A'      public  getName (n:A ){         return  n.name  === this .name      } } const  a1 = new  A ()const  a2 = new  A ()a1.getName (a2) 
16 - 静态成员 注意:
 特殊的静态名称不安全,避免使用:name、length、call等
Typescript中没有静态类的概念,因为js中还有函数和普通对象表示
class  Person  {         static  a = 1           protected  static  b = 1      static  SayHello (){         console .log ('hi' );              } } class  Children  extends  Person  {    constructor (         super ()         console .log (Person .b );     } } Person .SayHello (); 
17 - static区块 注意:static区块和constructor的区别:
static区块可以在实例没创建之前就可以调用,而constructor要在创建实例才调用 
class  Person  {    static  #count = 0 ;     get  count (){         return  Person .#count;     }     static  {         const  lastInterce = {length :100 }         Person .#count+=lastInterce.length      } } const  person = new  Person ();console .log (person.count );
18 - 泛型类 class  Box <T> {    contents :T     constructor (value:T ) {         this .contents  = value     }          static  id :T  } const  box = new  Box <string >('Hello World' )const  box1 :Box <string > = new  Box ('Hello World' )const  box2 = new  Box ('Hello World' )
19 - 类运行中的this class  Box  {    name = 'Box'      getName = ()=> {           return  this .name      }     getName (         return  this .name      } } const  box = new  Box ()const  obj = {    name :'obj' ,     getName :box.getName  } console .log (obj.getName ())
20 - this类型 class  Box  {    content :string  = ''      sameAs (ohter:this  ){         return  ohter.content  === this .content      } } class  DerivedBox  extends  Box  {    otherContent :string  = '?'  } const  base = new  Box ()const  derived = new  DerivedBox ()derived.sameAs (base)  
21 - 基于类型守卫的this class  FileSystemObject  {    isFile ():this  is FileRep {         return  this  instanceof  FileRep ;     }     isDirectory ():this  is Directory {         return  this  instanceof  Directory ;     }     isNetWorked ():this  is NetWorked  & this {         return  this .NetWorked      }     constructor (public  path:string ,private  NetWorked:boolean      } } class  FileRep  extends  FileSystemObject {    constructor (path:string ,public  content:string  ){         super (path,false );     } } class  Directory  extends  FileSystemObject  {    children :FileSystemObject []     constructor (         super ('' ,true );         this .children =[]; } } interface  NetWorked  {    host :string  } const  fso :FileSystemObject  = new  FileRep ('/index.txt' ,'foo' )if (fso.isFile ()){         fso.content  }else  if (fso.isDirectory ()){           fso.children  }else  if (fso.isNetWorked ()){          fso.host  } class  Box <T>{    value?:T     hasValue ():this  is {value :T}{         return  this .value  !== undefined ;     } } const  box :Box <string > = new  Box ()box.value  = 'hello'  if (box.hasValue ()){    console .log (box.value );      } 
22 - 参数属性 class  Person  {         constructor (public  name:string ,protected  age:number ,private  gender:string          this .name =name;         this .age =age;         this .gender =gender;     } } 
23 - 类表达式 const  someName = class <T>{    name :string      constructor (value:string  ){         this .name  = value     } } const  n = new  someName ('123' )console .log (n.name );
24 - 抽象类和成员 abstract  class  Base  {         abstract  getName ():string      SayHello (){         console .log (`Hello ${this .getName()} ` );              } } class  Child  extends  Base  {         getName (         return  "Child"      } } const  child = new  Child ()console .log (child.getName ());child.SayHello (); function  HandleTest (Constor:new  ()=>Base ){    const  a = new  Constor ()     console .log (a.getName ());     a.SayHello () } HandleTest (Child )
25 - 类之间的关系 class  A1 {    name :string  ='pan'      age :number  = 18  } class  A2 {    name :string  ='xiaopan'      age :number  = 20  } const  a1 :A2  = new  A1 ()class  Test  {} function  fn (test:Test ){} fn (window )fn (document )fn (100 )
基础篇(小满扩展) 01 - Object、object、{}的区别 let  a1 :Object  = 1 let  a2 :Object  = "1" let  a3 :Object  = []let  a4 :Object  = {}let  a5 :Object  = new  Date ()let  a6 :Object  = ()=> 12 let  a :object ='123' let  a1 :object = 123 let  a2 :object = true let  a3 :object =[]let  a4 :object ={}let  a5 :object =()=> 123 let  a :{}='123' let  a1 :{}= 123 let  a2 :{}= true let  a3 :{}=[]let  a4 :{}={}let  a5 :{}=()=> 123 let  b :{} = {name :123 } b.age  = 1  
02 - 后端接口怎么定义 interface  A{    name :string      age :number      [key :string ]:any  } const  res :A = {    name :'xiaopan' ,     age :123 ,     f :0  } function  handleTest (...agrs:number [] ){    const  a :IArguments  = arguments  } 
03 - 在对象中定义this interface  A {    user :string [],     fn :(this :A,a:string  void  } let  res :A = {    user :['pan' ,'xiao' ],          fn (this :A,a:string          this .user .push (a)     } } res.fn ("1" );  
04 - 常用的一些的内置类型 let  a :Number  = new  Number (1 )let  b :String  = new  String ('hello' )let  time :Date  = new  Date ()let  regExp :RegExp  = new  RegExp ('\\w+' ) let  error :Error  = new  Error ('Error occurred' )let  xml :XMLHttpRequest  = new  XMLHttpRequest ()const  dom = document .querySelector ('div' )const  dom2 = document .querySelector ('footer' )const  doms1 :NodeList  = document .querySelectorAll ('div' )const  doms2 :NodeListOf <HTMLDivElement  | HTMLElement > = document .querySelectorAll ('header' )const  local :Storage  = localStorage const  cookie :string  = document .cookie const  lo :Location  = locationconst  promise :Promise <string > = new  Promise ((res )=> res ('done' ))
05 - vue简写版 interface  Options {    el :string  | HTMLElement ; } interface  Vuecls {    options :Options ;     init ():void ; } interface  Vnode {    tag :string      text?:string       children?:Vnode [] } class  Dom  {         private  createElement (el: string  ){         return  document .createElement (el);     }          private  setText (el:HTMLElement, text:string  | null  ){         el.textContent  = text;     }          render (data:Vnode ){                  let  root = this .createElement (data.tag );                  if (data.children  && Array .isArray (data.children )){                          data.children .forEach (item =>                                  let  child =  this .render (item)                                  root.appendChild (child)             })         }else {                          this .setText (root, data.text  as  string );         }                  return  root     } } class  Vue  extends  Dom  implements  Vuecls {    options : Options ;     constructor (options: Options ){         super ()         this .options  = options;         this .init ();     }     init ():void {                  let  data :Vnode  = {             tag :'div' ,             children :[                 {tag :'div' ,text :'hello' },                 {tag :'div' ,text :'world' }             ]         }                  let  app = typeof  this .options .el  === 'string'  ? document .querySelector (this .options .el ) : this .options .el ;                  app?.append (this .render (data))     } } new  Vue ({    el :'#app'  }) 
06 - const枚举 const  enum  Tyeps  {    success,     fail } const  res :number  = 0 if (res === Tyeps .success ){} "use strict" ;const  res = 0 ;if  (res === 0  ) {}  enum  Tyeps  {     success,     fail } const  res :number  = 0 if (res === Tyeps .success ){} "use strict" ;var  Tyeps ;(function  (Tyeps ) {     Tyeps [Tyeps ["success" ] = 0 ] = "success" ;     Tyeps [Tyeps ["fail" ] = 1 ] = "fail" ; })(Tyeps  || (Tyeps  = {})); const  res = 0 ;if  (res === Tyeps .success ) {} 
07 - 反向映射枚举 enum  Types {    success= 2312  } const  success = Types .success  const  type  = Types [2312 ] console .log (`type:${type } ` ,`success:${success} ` );
08 - 类型层次 
09 - Symbol类型 const  num1 :symbol  = Symbol ("1" ) const  num2 :symbol  = Symbol ("1" )  console .log (num1 === num2);  console .log (Symbol .for ("1" ) === Symbol .for ("1" )); 
10 - 迭代器/生成器 function * fn (	yield  1      yield  2      yield  3      yield  4      yield  5  ) let  g = fn ()g.next () g.next () g.next () const  set = new  Set ([1 , 2 , 3 , 4 , 5 ,1 ,2 ,4 ]); const  map = new  Map () const  obj = [1 ,2 ,3 ]map.set (obj,1 ) const  each  = (value:any  )=>{    let  It :any  = value[Symbol .iterator ]()     let  next :any  = {done :false }     while (!next.done ){         next = It .next ()         if (!next.done ){             console .log (next.value );         }     } } for (let  i of  obj){    console .log (i) } let  [a,b,c] = [1 ,2 ,3 ]const  obj3 = {    max :5 ,     current :0 ,     [Symbol .iterator ](){         return {             current :0 ,             max :this .max ,             next (                 if (this .current  === this .max ){                     return {                         value :undefined ,                         done :true                      }                 }else {                     this .current ++;                     return {                         value :this .current ,                         done :false                      }                 }             }         }     } } for (let  i of  obj3){    console .log (i);      } 
11 - 泛型封装axios(简易版) const  axios = {    get<T>(url :string ):Promise <T>{         return  new  Promise ((resolve,reject )=> {             let  xml :XMLHttpRequest  = new  XMLHttpRequest ()             xml.open ('GET' ,url)             xml.onreadystatechange  = ()=> {                 if (xml.readyState  === 4  && xml.status  === 200 ){                     resolve (JSON .parse (xml.responseText ))                 }             }             xml.send (null )         })     } } interface  Data {    message :string ,     code :number  } axios.get <Data >('./db.json' ).then (res =>     console .log (res); }) 
12 - keyof高级用法 interface  Obj  {    name :string ,     age :number ,     dec :string  } type  Options <T extends  Obj >= {    [key in  keyof T]?:T[key] } type  B = Options <Obj >
13 - ts配置文件 "compilerOptions" : {  "incremental" : true ,    "tsBuildInfoFile" : "./buildFile" ,    "diagnostics" : true ,    "target" : "ES5" ,    "module" : "CommonJS" ,    "outFile" : "./app.js" ,    "lib" : ["DOM" , "ES2015" , "ScriptHost" , "ES2019.Array" ],    "allowJS" : true ,    "checkJs" : true ,    "outDir" : "./dist" ,    "rootDir" : "./" ,    "declaration" : true ,    "declarationDir" : "./file" ,    "emitDeclarationOnly" : true ,    "sourceMap" : true ,    "inlineSourceMap" : true ,    "declarationMap" : true ,    "typeRoots" : [],    "types" : [],    "removeComments" :true ,    "noEmit" : true ,    "noEmitOnError" : true ,    "noEmitHelpers" : true ,    "importHelpers" : true ,    "downlevelIteration" : true ,    "strict" : true ,    "alwaysStrict" : true ,    "noImplicitAny" : true ,    "strictNullChecks" : true ,    "strictFunctionTypes" : true ,    "strictPropertyInitialization" : true ,    "strictBindCallApply" : true ,    "noImplicitThis" : true ,    "noUnusedLocals" : true ,    "noUnusedParameters" : true ,    "noFallthroughCasesInSwitch" : true ,    "noImplicitReturns" : true ,    "esModuleInterop" : true ,    "allowUmdGlobalAccess" : true ,    "moduleResolution" : "node" ,    "baseUrl" : "./" ,    "paths" : {           "jquery" : ["node_modules/jquery/dist/jquery.min.js" ]   },   "rootDirs" : ["src" ,"out" ],    "listEmittedFiles" : true ,    "listFiles" : true  }   "include" : [   "src/**/*"  ],  "exclude" : [    "demo.ts"  ],  "files" : [    "demo.ts"  ] 
14 - namespace命名空间 namespace  ios {    export  let  a = 1  } namespace  android {    export  let  b = 2      export  namespace  android_inter{         export  let  c = 3      } } console .log (ios.a );console .log (android.b );console .log (android.android_inter .c );
15 - 三斜线指令 namespace  A{    export  let  a = 1  } namespace  A {    export  let  x = 1 ;     export  function  f ( } console .log (A.a );
16 - 声明文件(包名.d.ts) 有一些第三方没有自己相对应的包名声明文件。以下为解决方案:
使用社区提供的声明文件进行下载,下载
@types/包名        // 例如:@types/node
 
下载404使用第二种方法,进行手动编写声明文件
declare  module  '包名'  {    exprots default  导出内容 } 
 
以下为一个以express的实例 
declare  module  'express'  {    interface  App  {         use :(path:string ,router:Router )=> void          listen :(port:number ,cb:()=>void  )=> void      }     interface  Router  {         get (path :string ,cb :(req:any ,res:any  )=> void ):void      }     interface  Express  {         ():App ,         Router ():Router      }     const  express : Express ;     export  default  express } 
17 - Mixin混入 
将多个类或对象等混入在一起
 
interface  A {    name :string  } interface  B {    age :number      fn :()=> void      dec :Dec  } type  Dec  = [number ,number ,{name :string }]const  res1 :A = {    name :'pan'  } const  res2 :B = {    age :18 ,     fn :()=> {console .log ('fn' )},     dec :[1 ,2 ,{         name :'pan' ,     }] } const  res3 = {...res1,...res2}const  res4 = Object .assign ({},res1,res2)const  a = structuredClone (res1)
class  logger  {    log (msg:string  ){         console .log (msg);     } } class  Html  {    render (res:string  ){         console .log (res);              } } class  App  {    run (         console .log ("run" );     } } type  Constructor <T> = new  (...args : any []) => T;function  Mixins <T extends  Constructor <App >>(Base :T){    return  class  extends  Base {         private  logger :logger;         private  html :Html ;         constructor (...args: any [] ){             super (...args)             this .logger  = new  logger ();             this .html  = new  Html ();         }         run (): void  {             this .logger .log ('hello' )         }         render (             this .logger .log ('hello' )             this .html .render ('<h1>hello</h1>' );         }     } } const  mixins = Mixins (App )const  app = new  mixins ()app.run () app.render () 
18 - 装饰器(Decorator) 类装饰器(ClassDecorator) 就是对class类进行拓展修饰
         const  Base :ClassDecorator  = (target )=> {                  target.prototype name  = '123' ;                  target.prototype fn  = ()=> {             console .log ('fn' );         }     }     @Base      class  Http {     } const  Base  = (str: string  ) => {  const  fn : ClassDecorator  = (target ) =>  {     target.prototype name  = "123" ;     target.prototype fn  = () =>  {       console .log ("fn" ,str);     };   };   return  fn; }; @Base ("pan" )class  Http  {}
方法装饰器 (MethodDecorator) 就是对类中方法进行修饰
import  axios from  'axios' ;const  Get  = (url:string  )=>{  const  fn :MethodDecorator  = (target,key,descriptor:PropertyDescriptor )=> {     axios.get (url).then (res =>       descriptor.value (res.data )     })   }   return  fn } class  Http  {  @Get ('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10' )   getList (data:any  ){     console .log (data);   } } 
参数装饰器(ParameterDecorator) 对参数进行修饰
import  'reflect-metadata' import  axios from  'axios' ;const  Get  = (url:string  )=>{  const  fn :MethodDecorator  = (target,key,descriptor:PropertyDescriptor )=> {          const  key1 = Reflect .getMetadata ('key' ,target)     axios.get (url).then (res =>              descriptor.value (key1?res.data [key1]:res.data )     })   }   return  fn } const  Result  = (     const  fn :ParameterDecorator  = (target,key,index )=> {     console .log (target,key,index);          Reflect .defineMetadata ('key' ,"result" ,target)   }   return  fn } class  Http  {  @Get ('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10' )   getList (@Result () data:any      console .log (data);   } } 
基础篇(构建TS项目) 01 - Rollup构建TS项目 安装依赖
import  path from  "path" import  ts from  "rollup-plugin-typescript2" import  livereload from  "rollup-plugin-livereload" import  serve from  "rollup-plugin-serve" import  replace from  "rollup-plugin-replace" export  default  {    input : './src/index.ts' ,     output :{         file : path.resolve (__dirname,'../lib/index.js' ),         format :'cjs' ,         sourcemap :true      },     plugins :[         ts (),         livereload (),         serve ({             open :true ,             openPage :'/public/index.html' ,             port :1988          }),         replace ({             'process.env.NODE_ENV' :JSON .stringify (process.env .NODE_ENV )         })     ] } 
import  path from  "path" import  ts from  "rollup-plugin-typescript2" import  { terser } from  "rollup-plugin-terser" import  replace from  "rollup-plugin-replace" const  isDev  = (env .NODE_ENV  === 'development' export  default  {    input : 'src/index.ts' ,     output :{         file : path.resolve (__dirname,'../lib/index.js' ),         format :'cjs' ,         sourcemap :true      },     plugins :[         ts (),         terser ({             compress :{                 drop_console :!isDev ()             }         }),         replace ({             'process.env.NODE_ENV' :JSON .stringify (process.env .NODE_ENV )         })     ] } 
{   "name" : "rollup_ts" ,   "version" : "1.0.0" ,   "description" : "" ,   "main" : "index.js" ,   "scripts" : {     "test" : "echo \"Error: no test specified\" && exit 1" ,     "dev" : "cross-env NODE_ENV=development rollup -c ./config/rollup.config.dev.js -w" ,     "build" : "cross-env NODE_ENV=production rollup -c config/rollup.config.prod.js"    },   "keywords" : [],   "author" : "" ,   "license" : "ISC" ,   "devDependencies" : {     "cross-env" : "^7.0.3" ,     "rollup-plugin-livereload" : "^2.0.5" ,     "rollup-plugin-node-resolve" : "^5.2.0" ,     "rollup-plugin-replace" : "^2.2.0" ,     "rollup-plugin-serve" : "^1.1.0" ,     "rollup-plugin-terser" : "^7.0.2" ,     "rollup-plugin-typescript2" : "^0.31.1" ,     "typescript" : "^4.5.5"    } } 
02 - webpack构建TS项目(简单搭建构架) const  path = require ('path' );const  HtmlWebpackPlugin  = require ('html-webpack-plugin' );const  config = {  entry : './src/index.ts' ,   mode :'development' ,   output :{     path :path.resolve (__dirname, 'dist' ),     filename :'bundle.js'    },   resolve :{     extensions : ['.ts' , '.js' ]   },   module :{     rules :[         {             test : /\.ts/ ,             use : 'ts-loader' ,             exclude : /node_modules/          }     ]   },   plugins :[     new  HtmlWebpackPlugin ({       template : './public/index.html'      })   ] }; module .exports  = config;
{   "name" : "webpack_ts" ,   "version" : "1.0.0" ,   "description" : "" ,   "main" : "index.js" ,   "scripts" : {     "test" : "echo \"Error: no test specified\" && exit 1" ,     "dev" :"webpack-dev-server" ,     "build" :"webpack"    },   "keywords" : [],   "author" : "" ,   "license" : "ISC" ,   "devDependencies" : {     "html-webpack-plugin" : "^5.6.0" ,     "ts-loader" : "^9.5.1" ,     "typescript" : "^5.3.3" ,     "webpack" : "^5.89.0" ,     "webpack-cli" : "^5.1.4" ,     "webpack-dev-server" : "^4.15.1"    } } 
03 - esbuild+swc构建TS项目 介绍:
esbuild 是go语言编写的并且是多线程执行,性能是js的好几十倍,所以很快。
无需缓存即可实现基本打包 
支持ES6跟CommonJS模块 
支持ES6 Tree Shaking 
体积小 
插件化 
其他 
内置支持编译JSX 
 
swc 则宣称其比Babel快20倍(四核情况下可以快70倍)
swc 是用rust写的,所实现的功能跟babel一样,es6语法转es5,但是速度比babel更快,前端基建工具使用rust的是越来越多了,未来可能还会有一个替代postCss的。
import  esbuild from  'esbuild' ; import  swc from  '@swc/core' ; import  fs from  "node:fs" await  esbuild.build ({         entryPoints : ['src/index.ts' ],          loader :{         '.ts' : 'ts' ,         '.js' : 'js' ,         '.jsx' : 'jsx' ,         '.tsx' : 'tsx'      },          treeShaking :true ,          define :{         'process.env.NODE_ENV' : '"production"' ,     },          plugins :[                  {             name :"swc-loader" ,             setup (build ){                                  build.onLoad ({filter :/src\/.(js | ts | tsx | jsx)$/ },(args )=> {                                          const  content = fs.readFileSync (args.path ,'utf-8' )                                          const  {code} = swc.transformSync (content,{                         filename :args.path                      })                                          return  {                         contents :code                     }                 })             }         }     ],     outdir :'dist'  }) 
注意:在package.json中加上type:”module”
启动指令:ts-node-esm config.ts
 
04 - TS编写发布订阅模式 
	
具体代码:on订阅/监听      emit发布/注册     once只执行一次   off解除绑定
interface  List  {  [key : string ]: Function ; } interface  EventFn  {  on (name : string , fn : Function ): void ;   emit (name : string , ...agrs : any []): void ;   off (name : string ): void ;   once (name : string , fn : Function ): void ; } class  Dispatch  implements  EventFn  {  private  list : List ;   constructor (     this .list  = {};   }   on (name: string , fn: Function  ) {     this .list [name] = fn;   }   emit (name: string , ...agrs: any [] ) {     if  (this .list [name]) {       this .list [name].apply (this , agrs);     } else  {       console .error (`名称错误${name} ` );     }   }   off (name: string  ) {     if  (this .list [name]) {       delete  this .list [name];     } else  {       console .error (`名称错误${name} ` );     }   }   once (name: string ,...agrs: any [] ) {     if  (this .list [name]) {       this .emit (name,...agrs);       this .off (name);     } else  {       console .error (`名称错误${name} ` );     }   } } export  default  new  Dispatch ();
05 - set、map、weakset、weakmap使用 
set和map  
const  set :Set <number > = new  Set ([1 , 2 , 3 , 4 , 4 ]); set.add (5 )  set.delete (1 )  set.clear ()  set.has (1 )  set.forEach   set.entries ()  set.keys ()  const  obj = {name :"pan" }const  map :Map <Object ,any > = new  Map () map.set (obj,"asnfa" )  map.delete (obj)  map.has (obj)  map.clear ()  map.entries ()  map.keys ()  
weakset 和weakmap  
注意:weakset 和weakmap为弱引用不会被计入垃圾回收机制的
 
let  obj :any  = {name :'pansida' } const  weakmap :WeakMap <Object ,any > = new  WeakMap ()weakmap.set (obj, '123' )  obj = null   console .log (weakmap.get (obj)) let  arr :any  = [1 ,2 ,3 ,4 ] const  weakset :WeakSet <any > = new  WeakSet ()weakset.add (arr)  arr = null   console .log (weakset.has (arr)) 
06 - proxy和Reflect proxy就是数据劫持
const  obj = { name : "xiaopan"  };const  objProxy = new  Proxy (obj, {     get (target, key, receiver ) {     return  Reflect .get (target, key, receiver);   },      set (target, key, value, receiver ) {     return  Reflect .set (target, key, value, receiver);   },      deleteProperty (target, key ) {     return  Reflect .deleteProperty (target, key);   },      has (target, key ){     console .log ("我触发了" );     return  Reflect .has (target, key);   },      ownKeys (target ){     return  Reflect .ownKeys (target);   },      apply (target, thisArg, argArray ){   },      construct (target,thisArg,argArray ){          return  {}   } }); if ('xiaopan'  in  objProxy){    console .log (111 ); } 
const  list :Set <Function > = new  Set ()const  autorun  = (cb:Function  )=>{  if (!list.has (cb)){     list.add (cb)   } } let  observable = <T extends  object >(param:T )=> {  return  new  Proxy (param,{     get (target,value ){       return  Reflect .get (target,value)     },     set (target,value,newValue ){       list.forEach (fn =>fn ())       return  Reflect .set (target,value,newValue)     }   }) } autorun (()=> {  console .log ('我被改变了' );    }) const  obj =  observable ({name :'张三' ,age :20 })obj.name  = '李四'  
07 - 类型守卫(面试题) const  isObject  = (data:any  )=> ({}).toString .call (data) === '[object Object]' ;const  isnumber = (data :any ):data is number  => typeof  data === 'number' ;const  isstring = (data :any ):data is string  => typeof  data === 'string' ;const  isfunction = (data :any ):data is Function  => typeof  data === 'function' ;function  handleTest (data:any  ){  if (isObject (data)){     Object .keys (data).forEach (index =>       let  val = data[index]        if (isnumber (val)){         data[index] = val.toFixed (2 )       }       if (isstring (val)){         data[index] = val.trim ()       }       if (isfunction (val)){         data[index]()       }     })   } } const  obj = {  a :10.3412 ,   b :'   hello world   ' ,   c :function (     console .log (this );     console .log ('hello function' )   } } handleTest (obj)
08 - 协变、逆变、双向协变   (类型兼容性) 所谓的类型兼容性,就是用于确定一个类型是否能赋值给其他的类型。ypeScript中的类型兼容性是基于结构类型的(也就是形状),如果A要兼容B那么A至少具有B相同的属性。
interface  A {  name :string ,   age :number  } interface  B {  name :string ,   age :number ,   gender :string  } let  a :A = {name :'a' , age :18 }let  b :B = {name :'b' , age :18 , gender :'male' }a = b let  fnA  = (p:A )=>{};let  fnB  = (p:B )=>{};fnB = fnA; fnB = fnA fnA = fnB 
09 - 泛型工具 
Partial属性可选的意思
Required属性必选的意思
Pick提取部分属性
Exclude排除部分属性
Omit排除部分属性并且返回新的类型
Record 约束对象key以及value
ReturnType 获取函数类型的返回值
 
Partial
interface  A {  name : string ;   age : number ;   gender : string ; } type  PartialA  = Partial <A>;type  PartialATest <T> = {  [P in  keyof T]?: T[P] } 
Required
interface  A {  name?: string ;   age?: number ;   gender?: string ; } type  PartialA  = Required <A>;type  PartialATest <T> = {  [P in  keyof T]-?: T[P] } 
Pick
interface  A {  name?: string ;   age?: number ;   gender?: string ; } type  PickA  = Pick <A, 'name'  | 'age' >;type  PickATest <T,K extends  keyof T> = {  [Key  in  K]:T[Key ] } 
Exclude
type  ExcludeA  = Exclude <'name'  | 'gender'  | 'age' ,'age' >;type  ExcludeATest <T,K> = T extends  K ? never  : T 
Omit
interface  A {  name?: string ;   age?: number ;   gender?: string ; } type  OmitA  = Omit <A, 'a' >;type  OmitATest <T,K> = Pick <T,Exclude <keyof T,K>>
Record
type  Key  = 'name'  | 'age'  | 'gender' type  Value  = 'x'  | 'y'  | 'z' type  Test  = Record <Key , Value >type  Test1  = keyof any  type  RecordTest <T extends  Test1 ,K> = {  [P in  T]: K } const  test : RecordTest <Key ,Value > = {  name : 'x' ,   age : 'y' ,   gender : 'z'  } 
ReturnType
let  fn  = (1 ,2 ,3 ]type  ReturnTest  = ReturnType <typeof  fn> type  ReturnTypeTest <T> = T extends  (...agrs :any [])=>infer R? R :never type  ReturnTest2  = ReturnTypeTest <typeof  fn> 
 
10 -  infer 关键字 interface  User  {  name : string ;   age : number ; } type  PromiseType  = Promise <User >type  GetPromiseType <T> = T extends  Promise <infer X> ? X : T;type  T = GetPromiseType <PromiseType >type  PromiseType1  = Promise <Promise <User >>type  GetPromiseType1 <T> = T extends  Promise <infer X> ? GetPromiseType1 <X> : T;type  T1  = GetPromiseType1 <PromiseType1 >type  inferTest1<T> = T extends  { name : infer U,age :infer U } ? U : never ;type  T2  =  inferTest1<User > type  inferTest2<T> = T extends  {a :(name:infer U )=> void ,b :(age:infer U )=> void }? U :Ttype  T3  = inferTest2<{a :(name:string  )=> void ,b :(age:number  )=> void }> 
11 - infer 提取元素妙用 type  Arr  = ['a' ,'b' ,'c' ]type  First <T extends  any []> = T extends  [infer First ,...agrs :any []]? First :never type  FirstTest  = First <Arr >type  Last <T extends  any []> = T extends  [...agrs :any [],infer Last ]? Last  :never type  LastTest  = Last <Arr >type  Pop <T extends  any []> = T extends  [...infer First ,unknown ] ? First  :never type  PopTest  = Pop <Arr >type  Shift <T extends  any []> = T extends  [unknown ,...infer Last ] ? Last  :never type  ShiftTest  = Shift <Arr >
12 - TS用法递归 type  Arr  = [1 ,2 ,3 ,4 ]type  ReverseArr <T extends  any []> = T extends  [infer First ,...infer Rest ]?[...ReverseArr <Rest >,First ]:Ttype  newArr = ReverseArr <Arr > 
13 - 插件编写(localstroageTime 编写 有时间的localstroage) export  enum  Dictionaries  {    permanent = 'permanent' ,     expire = '__expire__'  } 
import  { Dictionaries  } from  "../enum/index" export  type  Key  = string ;export  type  TimeLimit  = number  | Dictionaries .permanent ;export  type  Data <T> = {  value : T;   [Dictionaries .expire ]: Dictionaries .permanent  | number ; }; export  interface  Result <T> {  message : string ;   value : T | null ; } export  interface  LocalStorageTimeCls  {  get<T>(key : Key ): Result <T | null >;   set<T>(key : Key , value : T, TimeLimit : TimeLimit ): void ;   remove (key :Key ): void ;   clear (): void ; } 
import  {Data , Key , LocalStorageTimeCls ,Result ,TimeLimit } from  "./types/index" import  {Dictionaries } from  "./enum/index" class  LocalStorageTime  implements  LocalStorageTimeCls {    get<T>(key :Key ):Result <T | null >{         const  value = localStorage .getItem (key)         if (value){             const  obj :Data <T> = JSON .parse (value)             const  date = new  Date ().getTime ()             if (typeof  obj.__expire__  === "number"  && obj.__expire__  < date){                 this .remove (key)                 return  {                    message :"缓存已过期" ,                    value :null                  }             }else {                 return  {                    message :"获取成功" ,                    value :obj.value                  }             }         }else {             return  {                 message :`你的${key} 值无效!` ,                 value :null              }     }     }     set (key:Key,value:any ,TimeLimit:TimeLimit = Dictionaries.permanent ){         const  data = {            key,            value,            [Dictionaries .expire ]:TimeLimit           }         localStorage .setItem (key,JSON .stringify (data));     }     remove (key:Key ){         localStorage .removeItem (key)     }     clear (         localStorage .clear ()     } } export  default  new  LocalStorageTime ()