typescript基础

102 阅读15分钟

前言

typescript作为javascirpt超集,主要在开发中基础也是最重要的就是约定类型增强代码安全性和可读性,至于类型算法的方面在本文暂时不过多展开

基础类型

1.string
    let name:string = 'bob';
    name = 'smith';
    
2.number
    let dec:number = 6;//十进制
    let hex:number = 0Xf00d;//十六进制
    let oct:number = 0o744;//八进制
    let bin:number = 0b1010;//二进制
    
    //编译后
    var dec = 6;//十进制
    var hex = Oxf00d;//十六进制
    var oct = 484;//八进制
    var bin = 10;//二进制
    
3.boolean
       let isDone:boolean = false;
       
4.array
    定义非联合类型数组
        使用泛型定义类型:
            let arr:Array<number> = [1,2,3];
            
        使用[]定义:
            let arr:number[] = [1,2,3];

    定义联合类型数组
        使用泛型定义类型:
            let arr1:Array<number | string> = [1,'2',3];
            
        使用[]定义:
            let arr:(number | string)[] = [1,2,'4'];
            
    元组:
        const arr4:[string,number,boolean] = ['1',2,true];
        const arr6:[string,number?,boolean?] = ['linbudu'];
        const arr6:[string,number?,boolean?] = ['linbudu',,]
        
    具名元祖:
        const arr7:[name1:string,age:number,male:boolean] = ['linbudu',599,true];
        const [name1,age,male] = arr7;
        console.log(name1,age,male);//'linbudu',599,true
        
        //编译后
        var arr7 = [
            'linbudu',
            599,
            true,
        ]
        
        var name1 = arr7[0],age = arr7[1],male = arr7[2];
        
5.undefined
    let u:undefined = undefined;
    
6.null
    let n:null = null;

7.any
    //允许我们对any类型的值进行任何操作,而无需事先执行任何类型的检查
    
8.unknown
    //作为被赋值方,可以被任何类型进行赋值
    //作为赋值给其他变量时,除了unknown和any外,其余类型不能进行赋值

9.void
    //void类型描述函数内部没有return
    function abc():void{
        console.log(1);
    }
    
10.never
    //不存在值的类型
    
    // 异常
    function err(msg: string): never { 
        throw new Error(msg); 
    }
    
    // 死循环
    function loopForever(): never { 
         while (true) {};
    }
   
11.symbol
    const symbolVar:symbol = Symbol('unique');
    

接口(interface)

//接口定义:
    interface 变量名{
        属性名:数据类型,
             //必选属性
                1.传入的参数名必须是定义的属性名
                2.传入的参数数据类型必须是规定的数据类型
                3.传入的参数个数必须和接口中定义的数量保持一致
						
        属性名?:数据类型,
             //可选属性
                1.传入的参数个数可有可无
                2.可以对预定义的传参,进行预定义
						
        readonly 属性名:数据类型,
             //可读属性
                1.传参的属性名和接口的属性名相同时,会被设置为可读
                2.属性为可读时,不能进行修改
       }
    
//函数类型:
        1.定义
            interface SearchFunc{
                (source:string,subStrng:string):boolean;
                //函数传入的参数,返回值类型
            }
				
            interface SearchFunc{
                (形参名1:数据类型1,形参名2:数据类型2):函数返回值类型
            }
				
            let mySearch:SearchFunc;
            mySearch = function(src:string,substring:string){
                //函数接口和定义的函数形参名称不需要一致,但形参类型保持一致
					
                let result = src.search(substring);
                return result > -1;
            }
            
//可索引的类型:描述对象索引的类型和相应的索引返回值类型
        1.定义:
            //TypeScript支持两种索引签名:字符串和数字
            //数字索引签名的返回值必须和字符串索引签名的返回值保持一致(默认数字索引也会转为字符串索引)
            interface StringArray{
                [index:number]:string;
            }
				
        2.使用:	
            let myArray:StringArray;
            myArray = ["Bob","Fred"];
				
            let myStr:string = myArray[0];	
            
//对象:
         interface Iperson{
               name:string;
               age:number;
               setTime(d: number):number;
               }

         class Person implements Iperson{
                name:string;
                age:number;
                setTime(d: number){
                    console.log(d);
                    return d;
                    };
                    
                constructor(h:string,m:number){
                    this.name = h;
                    this.age = m;
                    }
                 }
         }
                
         const obj:Iperson = {
                 name:'guang',
                 age:18,
                 setTime(a){
                      console.log(a);
                      return a;
                 }
          }

 //构造器:
         interface Iperson{
                 name:string,
                 age:number,
                 }
         
         interface PersonConstructor{
                 new(name:string,age:number):Iperson;
                 }

         function createPeson(ctor:PersonConstructor):Iperson{
                return new ctor('guang',18);
                }
                
         class Rperson implements Iperson{
                name:string;
                age:number;
                constructor(n:string,a:number){
                        this.name = n;
                        this.age = a;
                }
         }
                
         createPeson(Rperson);
         
         //interface的声明合并:
         interface User {
              name: string
              age: number
         }

         interface User {
              sex: string
         }
         
         //interface的类型继承
         interface inherit {
             mutation:string
         }
         
         interface pepole extends inherit {
             attitude:string;
         }

        //对应
        User 接口为 {
          name: string
          age: number
          sex: string 
        }
        
        //报错
        type TStringArray = {
          [index: number]: string;
        }

        type TStringArray = {
          [index: string]: string;
        }

type

//type可以对一些基础类型进行类型别名(type和interface区别之一)
//type会对类型进行覆盖,interface会对类型进行重叠
    情况1.
        //基础类型
        type Num = number;
        
        //联合类型
        type Type = number | string;
        type Arr = [string,number];
        
        //typeof获取类型
        let abc = 1;
        type Types = typeof abc;
        let def:Types = abc;
        
    情况2.
        //类型扩展
        type Person = {
              name: string;
              age: number;
        };

        type Employee = {
              sex: string;
        };

        type EmployeePerson = Person & Employee;

        let Nav:EmployeePerson = {
              name:'name',
              age:18,
              sex:"12'"
        }
        
    情况4.
        //对象
        type User = {
          name: string
          age: number
        };
    
    情况5.
        //函数
        type SetUser = (name: string, age: number)=> void;
        
    情况6.
        //结合泛型定义类型:
        type Call<T> = (data: T) => void;

继承

 情况1.
    //类继承接口
    interface ClockInterface {
      currentTime: Date;
    }

    class Clock implements ClockInterface {
      currentTime: Date;
      constructor(input:Date) { 
        this.currentTime = input;
      }
    }
    
 情况2.
    //接口继承接口
    interface Shape {
      color: string;
    }

    interface Square extends Shape {
      sideLength: number;
    }

    let obj123:Square = {
         color:'color',
         sideLength:12,
    }
    
 情况3.
    //接口继承类
    class type {
      name:string;
      age:number;
      constructor(a:string,b:number){
            this.name = a;
            this.age = b;
          }
    }

    interface Port extends type{
          name:string;
          age:number;
    }
    
 情况4.
     //类继承类
     class Person {
          name:string;
          age:number;
          constructor(name:string, age:number) {
                this.name = name
                this.age = age
          }

          running() {
            console.log('running!!!')
          }
    }

    class Student extends Person {
          sno:number
          constructor(name:string, age:number, sno:number) {
                        super(name, age)
                        this.sno = sno
          }

          studying() {
            console.log('studying!!!')
          }
    }

    const s1 = new Student('ice', 22, 200010)

    s1.running()
    s1.studying()

枚举(enum)

     //枚举可以定义一些带名字的常量
     //可以创建一组有区别的用例
       情况1.数字枚举,当有初始值时,后面的元素会按位置顺序以1递增
           enum Color{
                Red = 1,
                Green,
                Blue,
                }
                    
           console.log(Color.Red);//1
           console.log(Color.Green);//2
           console.log(Color.Blue);//3
           
       情况2.数字枚举,当没有初始值时,起始值默认为0
           enum Color{
                Red,
                Green,
                Blue
                }
            console.log(Red);//0
            console.log(Green);//1
            console.log(Blue);//2
			
       情况3.数字枚举,当没有初始值时,第一个成员的键值默认为0
            enum Color{
                Red,
                Green = 0,
                Blue,
                }
            console.log(Red);//0
            console.log(Green);//0
            console.log(Blue);//0
       
       情况4.数字枚举,反映射(根据值进行反向获取枚举中的元素名)
            enum Data{
                web = 1,
                tru = 2,
                tree = 3,
                }
                
            let a:string = Data[1]
            console.log(a);//web
			
       情况5.字符串枚举,若初始化中有字符串时,需要对全部元素初始化
            enum Data{
                web = '1',
                tru = '2',
                tree = '3',
                }
		
       情况6.常量枚举
            const enum Direction{
                    NORTH,
                    SOUTH,
                    EAST,
                    WEST
            }
	
            let dir:Direction = Direction.NORTH;
			
       情况7.枚举表达式
            1.一个枚举表达式字面量(主要是字符串字面量或数字字面量)
            2.一个对之前定义的常量枚举成员的引用(可以是在不同的枚举类型中定义的)
带括号的常量枚举表达式
            3.一元运算符 +, -, ~其中之一应用在了常量枚举表达式
            4.常量枚举表达式做为二元运算符 +, -, *, /, %, <<, >>, >>>, &, |, ^的操作对象。 若常数枚举表达式求值后为 NaN或 Infinity,则会在编译阶段报错。
            enum Demo{
                        None,
                        Read    = 1 << 1,
                        Write   = 1 << 2,
                        ReadWrite  = Read | Write,
                        // computed member
                        G = "123".length
                        }
                        

类型运算

    1.条件类型基础:extends ?
        interface A{
            a:string;
            }
            
        interface B{
            b:string;
            }
	
        type c = B extends A ? number : string;//等价于type C = number
	
    2.in可以遍历枚举类型,类似for...in
        type Example = 'a' | 'b' | 'c' | 'd';
        type Obj = {
            [T in Example]:string;//遍历Example把每个key都赋值string类型
            }
        //type Obj = {a:string;b:string;c:string;d:string};
	
    3.keyof作为索引类型查询操作符,就是取到类型的key
        interface Example{
            a:string;
            b:string;
            c:number;
            d:boolean;
            }
	
        type Keys = keyof Example;//等价于 type Keys = 'a' | 'b' | 'c' | 'd';
	
    4.索引访问接口属性:
        例1:
         type person = {
             name:"Angus";
             height:85;
         }['name'|"height"]
	
         //type person = 'Angus' | 85;//never会自动省略

        例2:
         type Clothes<source,types> = {
            [K in keyof source]:source[K] extends types ? K : never;
         }[keyof source]
		
         interface Example{
             name:string;
             height:number;
             home:string;
             }	
         type newType = Clothes<Example,string>;//type newType = "name | home"
		
        例3:
         interface Angus{
             name:string;
             height:number;
             wight:number;
             }

          type newAngus = Pick <Angus,'number' | 'height'>//{name:string;height:number}

          type Pick<T,K extends keyof T> = {
              [P in K] : T[P];
          }
	
        例4:
          type FileterType<Source,Types> = Pick<Source,
              {
                  [K in keyof Source]:Souce[k] extends Types ? K : never
              }[keyof Source]>
		
    5.类型约束:
        变量类型1 extends 类型2
	
    6.infer推导:
        infer R 代表待推断的返回值类型,方便后续作为变量使用
	
    例1:解构1
        type First<Tuple extends unknown[]> = Tuple extends [infer T,...infer R] ? T : never;
        type res = First<[1,2,3]>;
        //res = 1;
        
    例2:解构2
        type Unpacked<T> = T extends (infer R)[] ? R : T;
        //如果T是某个待推断类型的数组,则返回推断的类型,否则返回T
		
        type Ids = number[];
        type Names = string[];
		
        type idType = Unpacked<Ids>;//number
        type nameType = Unpacked<Names>;//string
		
    例3:使用约束条件获取对应类型
        type Response = Promise<number[]>;
        type Unpacked<T> = T extends Promise<infer R> ? R : T;
		
        type resType = Unpacked<Response>;//number[]
		
    例4:同一个类型变量在推断的值有多种情况的时候会推断为联合类型
        type Foo<T> = T extends {a:infer U;b:infer U} ? U : never;
		
        type T10 = Foo<{a:string;b:string}>;//string
        type T11 = Foo<{a:string;b:number}>;//string|number
		
    例5:
        type ElementOf<T> = T extends (infer R)[] ? R : never;
			
        type TTuple = [string,number];
        type Union = ElementOf<TTuple>;//Union类型为string|number
		
    例6:传参不知道传什么参数时,用泛型+infer获取对应类型
        type ref = React.MutableRefObject<G2plotStackedBar | undefined>;
	
        const chartRef = useRef<???>();

        改进:
            type ChartRef<T> = T extends React.MutableRefObjet<infer P> ? P : never;
				
            const chartRef = useRef<ChartRef<ref>>();
		
    例7:以上的结合,实现ref
            ref函数就是把这个值包裹成{value:T}这样的结构
            1.一般情况
                  type Ref<T=any>={
                                 value:T
                                 }

                  function ref<T>(value:T):Ref<T>

                  const count = ref(2);//对应为Ref<number>

                  count.value://number
				
            2.复杂情况
                function ref<T>(value:T):T extends Ref ? T : Ref<UnwrapRef<T>>

                //若情况为ref(ref(2)),内存的ref(2)返回的是Ref<number>,直接返回Ref<number>
                //若情况为ref(ref({a:1})),返回的是Ref<{a:number}>,则直接返回Ref<{a:numebr}>
                //若情况为ref(2),返回的是Ref<UnwrapRef<2>>,返回number类型
				
            3.UnwrapRef实现(解决ref嵌套问题):
                type UnwrapRef<T> = {
                    ref:T extends Ref<infer R> ? R : T,
                    other:T, 
                    }[T extends Ref ? 'ref' : 'other']
				
            4.进一步升级UnwrapRef
                type UnwrapRef<T> = {
                    ref: T extnds Ref<infer R> ? R : T,
                    object:{[K in keyof T]:UnwrapRef<[T[K]>},
                    other:T
                    }[T extends Ref ? 'ref' : T extends object ? 'object' : 'other']
				
            //若情况为ref({foo:ref(1),bar:ref(2)}),T的类型为object
            //对对象中的每一项都进行,分别为{foo:number}、{bar:number}
				
            typescript中常用的工具类型:
			1.Omit:Omit(a,b)接收两个参数,第一个是要编辑的基本类型,第二个是你要删除的类型
				例子:
					type Person = {
						name:stirng;
						sex:string;
					}
					type newPerson = Omit<Person,'name'>//{sex:string}
					type Omit<T,K extends keyof any> = Pick<T,Exclude<keyof T,K>>
					
			2.Partial:可以快速把接口类型中定义的属性变成可选的(Optional)
				例子:
					type Person = {
						name:string;
						sex:string;
					}

					type newPerson = Partial<Person>;//{name?:string;sex?:string}

					type Partial<T> = {
						[P in keyof T]?: T[P]
					}
					
			3.Exclude:用于删除类型集合中的指定类型(有问题)
				例子:
					type a = string | number;
					type newPerson = Exclude<a,string>;//number

					type Exclude<T,U> = T extends U ? never : T;
					
			4.Readonly:将接口所有属性变为只读的
				例子:
					type Person = {
						name:stirng;
						sex:string;
					}

					type newPerson = Readonly<Person>;
					//type newPerson = {readonly name:string;readonly sex:string;}
		
					type Readonly<T> = {readonly [P in keyof T]:T[P]}
					
			5.ReturnType:适用于获取函数T的返回类型
				例子:
					type T0 = RetrunType<()=>string>;//string
					type T1 = ReturnType<(s:string)=>void>;//void
					type T2 = ReturnType<()=>T>;//{}
					type T3 = ReturnType<()=>T>;//number[]
					type T4 = ReturnType;//any
					type T5 = ReturnType;//any
					type T6 = ReturnType;//Error
					type T7 = ReturnType;//Error
			
				    type ReturnType any> = T extends (...args: any) => infer R ? R : any;
                                                 

类型守卫

 //通过类型推导能力,会随着你的代码逻辑不断尝试收窄类型
    
 1.类型守卫
  //JavaScript中,用于检查变量类型的typeof,会返回"string"|"number"|"object"|"underfined"
  //Typescript中,用于类型查询的typeof,会返回的是一个TypeScript类型
        const str = "linbudu";
        const obj = { name: "linbudu" };
        const nullVar = null;
        const undefinedVar = undefined;
        const func = (input: string) => {
              return input.length > 10;
        };
        
     情况1:       
        type Str = typeof str; //'linbudu'
        let abc: Str = "linbudu";

        type Obj = typeof obj; //{name:string}
        let obj1: Obj = { name: "12" };

        type Null = typeof nullVar; //null
        let Null1: Null = null;

        type Undefined = typeof undefinedVar; //undefined
        let Undefined1: Undefined = undefined;

        type Func = typeof func; //(input:string)=>boolean
        let func1: Func = (input: string) => {
          return input.length > 0;
        };
        
     情况2:
         const func = (input: string) => {
          return input.length > 10;
            };

         const func2: typeof func = (name: string) => {
          return name === "linbudu";
            };
        
         //typeof后不允许表达式
         let isValid:typof isInputValid('linbudu');
         
     情况3:
         通过类型推导能力,它会随着你的代码逻辑不断尝试收窄类型
         function foo(input:string){
             if(typeof input === 'string'){};
             if(typeof input ==== 'number'){};
             //...
             }
		
         注意点:
             //typescript做不到跨函数上下文来进行类型的信息收集
             function isString(input:unknown):boolean{
                 return typeof input === 'string';
                 }
		
             function foo(input:string | number){
                if(isString(input)){
                    (input).replace('libudu','linbudu599');
                }
                if(typeof input === 'number'){
                
                }
             }
             
             //改进后
             function isString(input:unknown):input is string{
                return typeof input === 'string'
                }

             function foo(input:string | number){
                 if(isString(input)){
                    //报错,在这里变成了number类型
		(input).replace('linbudu','linbudu599');
                    }
                 if(typeof input === 'number'){
                     //...
                     }
                 }
                    
                    
        因为isString这个函数在另外一个地方,内部判断逻辑不在函数foo中.这里的类型控制流分析做不到跨函数上下文来进行类型的信息收集

        即isString函数称为类型守卫,在它的返回值中,我们不再使用boolean作为类型标注,而是使用is关键字来显示地提供类型信息

        is关键字 + 预期类型:
            表示这个函数成功返回true,那么is关键字前这个入参的类型,就会被这个类型守卫调用方后续的类型控制流分析收集到
			
 2.in的类型保护
        interface Foo{
            foo:strig;
            fooOnly:boolean;
            shared:number;
            }
        interface Bar{
            bar:string;
            barOnly:boolean;
            shared:number;
            }
	
        function handle(input:Foo | Bar){
            if('foo' in input){
                return input.fooOnly;
            }else{
                return input.barOnly;
                }
            }


    3.instanceof类型保护
            class FooBase{};
            class BarBase{};
	
            class Foo extends FooBase{
                fooOnly(){}
                }
            class Bar extends BarBase{
                barOnly(){}	
                }
            
            function handle(input:Foo } Bar){
                if(inpur instanceof FooBase){
                input.fooOnly();
                }else{
                    input.barOnly();
                    }
                }
                

类型断言

 //类型断言可以将一个范围更广的类型,指定为一个更加具体的类型
 语法一:值 as 类型
     let anyValue:any = 'zhangsan';
     let length1:number = (anyValue as string).length;
 
 语法二:<类型>值
     let anyValue:any = 'zhangsan';
     let length1:number = (<string>anyValue).length;
            

函数

 1.函数签名	

    方式一:
        function foo(name:string):number{
                return name.length;
                }
                
    方式二:
        const foo:(name:string) => number = function(name){
                return name.length;
                }
	
    方式三:
        type FuncFoo = (name:string)=>number;
        或
        interface FuncFooStruct{
            (name:string):number
            }
	
        const foo:FuncFoo = (name)=>{
            return name.length;
            }
            
 2.void函数
     function foo():void{
         console.log(1);
         }
    
 3.可选参数和默认参数
     //可选参数,使用?描述
     //可选参数必须位于必选参数之后
     function foo1(name:string = ‘name’,age?:number):number{
         const inputAge = age || 18;
         return name.length + inputAge;
         }

     function foo2(name:string,age = 18):number{
         const inputAge = age;
         return name.length +inputAge;
         }
         
 4.剩余参数
     function foo(arg:string,...rest:[number,boolean]){
    
     }
     foo('linbudu',18,true);
 
 5.重载
    function func(foo:number,bar:true):string;
    function func(foo:number,bar?:false):number;

    function func(foo:number,bar?:boolean):string | number{
         if(bar){
             return String(foo);
         }else{
             return foo * 599;
             }
         }

    const res1 = func(599);//number
    const res2 = func(599,true);//string
    const res3 = func(599,false);//number

    //拥有多个重载声明的函数在被调用时,是按照重载的声明顺序往下查找的

    //typescirpt中,重载只有一个具体实现,其重载体现在方法调用的签名上而非具体实现上
    //在c++中,重载体现在多个名称一致,但入参不同的函数实现不同

重载的定义:
        1.函数签名的定义:
            函数签名=函数名称+函数参数+函数参数类型+返回值类型 
        2.函数签名的类型:
            实现签名和重载签名
            
        3.完整的函数重载定义:
            3.1一个实现签名+一个或多个重载签名合成
            3.2外部调用函数重载定义的函数时,只能调用重载签名,不能调用实现签名
            3.3调用重载函数时,会根据传递的参数判断你调用哪个函数
            3.4只有一个函数体,只有实现签名配备了函数体.所有的重载签名都只有签名,没有配备函数体.
            3.5实现签名必须兼容所有重载签名该位置的参数类型
            
    函数重载的例子:
        //数据类型
        type MessageType = "image" | "audio" | string;
        type Message = { id: number; type: MessageType;sendmessage: string;};
        
        //定义数组
        let messages:Message[] = [
                {
                  id: 1, type: 'image', sendmessage: "你好啊,今晚咱们一起去三里屯吧",
                },
                {
                  id: 2, type: 'audio', sendmessage: "朝辞白帝彩云间,千里江陵一日还"
                },
                {
                  id: 3, type: 'audio', sendmessage: "你好!张无忌"
                },
                {
                  id: 4, type: 'image', sendmessage: "刘老根苦练舞台绝技!"
                },
                {
                  id: 5, type: 'image', sendmessage: "今晚王牌对王牌节目咋样?"
                }
        ]
	
        //重载签名
        //第一个根据数字id来查询单个消息的重载签名
            function getMessage(value: number, myname: string): Message
        //第二个根据消息类型来查询消息数组的重载签名
            function getMessage(value: MessageType, readRecordCount: number): Message[]
		
        //实现签名
            function getMessage(value: any, value2: any = 1) {
                if (typeof value === "number") {
                    return messages.find((msg) => { return 4 === msg.id })
                    } else {
                    return messages.filter((msg) => value === msg.type).splice(0, value2)
                    }
                }
	
        //调用函数
            getMessage(1, "df");
	
    方法重载的例子:
        class ArrayList{
            constructor(public element:Array<object>){
            }
		
        get(index:number){
            return this.element[index];
            }
		
        show(){
            this.element.forEach((ele)=>{
            console.log(ele);
            })
        }
		
        remove(value:number):number;
        remove(value:object):object;
        remove(value:any):any{
        this.element = this.element.filter((ele,index)=>{
                if(typeof value === 'number'){
                     return value !== index;
                   }else{
                     return value !== ele;
                     }
                   })
                     return value;
                   }
                }
	
            let stuOne = {stuname:"wangwu",age:23};
            let stuTwo = {stuname:"lisi",age:39};
            let stuThree = {stuname:"liuqi",age:31};
	
            let arrayList = new ArrayList([stuOne,stuTwo,stuThree]);
	
            arrayList.show();
	
            console.log('删除第一个学生');
	
            arrayList.remove(stuTwo);
	
            arrayList.show();
            
 6.异步函数、Generator函数等类型签名
         //异步函数
         async function asyncFunc():Promise<T>{
        
         }

         //Generator函数
         function* genFunct():Iterable<void>{
         
         }

         //异步Generator函数
         async function* asyncGenFunc():AsyncIterable<void>{
    
         }
   

//类的主要结构只有构造函数、属性、方法、访问符(Accessor) 
       class Foo{
           prop:string;
           
           constructor(inputProp:string){
                   this.prop = inputProps;
                   }

           print(addon:string):void{
                   console.log(`${this.prop}and${addon}`);
                   }
		
           get propA():string{
                   return `${this.prop}+A`;
                   }

           set propA(value:string){
                   this.prop = `${value}+A`;
                   }
           }
	
    修饰符(publicprivateprotectedreadonly):
            class中属性默认为public
                类和类的实例为两种概念,即一旦实例化完毕(出厂零件),那就和类(工厂)没关系,即不允许再访问受保护的成员.			
                public:此类成员在类、类的实例、子类中都能被访问
                protected:此类成员仅能在类和子类中被访问
                private:此类成员仅能在类的内部被访问
		
            静态成员(static)
                在类的内部,静态成员无法通过this来访问,需要通过Foo.静态成员名进行访问.
                静态成员挂载在函数体上,而实例成员挂载在原型上.
		
            继承、实现、抽象类
                基类(父类)、派生类(子类)
                    1.在派生类中覆盖基类方法时,我们并不难确保派生类的这一方法能覆盖基类方法
                        使用override关键字,如果基类中没有这个方法,派生类中有这个方法,则会报错
			
            抽象类:抽象类对类结构和方法的抽象(无法声明静态的抽象成员)
                    方式一:
                        abstract class AbsFoo{
                            abstract absProp:string;
                            abstract get absGetter():string;
                            abstract absMethod(name:string):string;
                            }
			
                        class Foo implements AbsFoo{
                            absPropr:string = 'linbudu';
                
                            get absGetter(){
                                return 'linbud';
                            }
                            
                            absMethod(name:string){
                                return name;
                                }
                        }
                           

泛型

    1.映射类型:
            type Factory<T> = T | number | string;
	
    2.索引类型:
            type Stringify<T> = {
                K in keyof T]?:T[K]
            }
	
    3.条件类型:
            type IsEqual<T> = T extends true ? 1 : 2;
            
            type A = IsEqual<true>;//1
            type B = IsEqual<false>;//2
            type C = IsEqual<'linbudu'>;//2
	
    4.泛型默认值:
            type Factory<T = boolean> = T | number | string;
            const foo:Factory = false;
	
    5.泛型约束:使用extends进行约束
            type ResStatus<ResCode extends number> = ResCode extends 10000 | 10001 | 10002 ? 'success' : 'failure';
	
            type Res1 = ResStatus<10000>;//'success'
            type Res2 = ResStatus<20000>;//'failure
            type Res3 = ResStatus<'10000'>;//Type 'string' does not satisfy the constraint 'number'
    
    6.多泛型关联:
            //多泛型参数其实就像接收更多参数多函数,其内部的运行逻辑(类型操作)会更加抽象,表现在参数(泛型参数)需要进行的逻辑运算(类型操作)会更加复杂
            type Conditional<Type,Condition,TruthyResule,FalsyResult> = Type extends Condition ? TruthyResult : FalsyResult;
		
            //'passed!'
            type Result1 = Conditional<'linbudu',string,'passed!','rejected!'>;
	
            //'rejected!'
            type Result2 = Conditional<'linbudu',boolean,'passed!','rejected!'>;