zoukankan      html  css  js  c++  java
  • TypeScript类型检查机制

    类型检查机制:TypeScript编译器在做类型检查时,所秉承的一些原则。

    作用:辅助开发,提高开发效率。

    一、类型推断

    不需要指定变量的类型(函数的返回值类型),TypeScript可以根据某些规则自动地为其推断出一个类型。

    1,基础类型推断

    let a //let a: any
    let b = 1 //let b: number
    let c = [] //let c: any[]
    let c2 = [1] //let c2: number[]
    
    //设置函数默认参数
    //确定函数返回值的时候
    //let function1: (x?: number) => number
    let function1 =(x=1)=> x+1  //x=>number //function1返回number类型

    2,最佳通用类型推断

    //最佳通用类型推断
    //从多个类型推断出一个类型的时候,尽可能的兼容类型
    
    let arr = [1,null] //let arr: (number | null)[]

    3,上下文类型推断

    上面两种类型推断都是从右向左的推断,也就是根据表达式右侧的值推断表达式左边变量的类型。还有一种类型推断是从左到右。这就是上下文类型推断。

    上下文类型推断通常发生在事件处理中。

    window.onkeydown = (event)=>{
        console.log(evevt.button)
    }

    用类型断言

    interface Foo{
        bar:number
    }
    // let foo = {} as Foo
    // foo.bar =1;
    
    //推荐
    let foo: Foo ={
        bar: 1
    }

    二、类型兼容性

    结构之间兼容:成员少的兼容成员多的

    函数之间兼容:参数多的兼容参数少的

     1,接口兼容性

    属性少的兼容属性多的

    //类型兼容性
    /**
     * X兼容Y:X(目标类型) = Y(源类型)
     */
    
     //接口兼容性
     interface X{
         a:any;
         b:any;
     }
    
     interface Y{
         a:any;
         b:any;
         c:any;
     }
    
     let x1:X ={a:1,b:2};
     let y1:Y={a:1,b:2,c:3}
    
     x1 = y1 //X可以兼容Y
    //  y1 =x1 //Property 'c' is missing in type 'X' but required in type 'Y'.

    2,函数的兼容性

     两个函数相互赋值的情况,即函数作为参数的情况。

    1, 目标函数的参数个数一定要等于多于原函数的个数

    函数中含义可选参数或者剩余参数的时候,也会遵循其他原则

    //1)参数个数
    let handler1 = (a:number) =>{}
    hof(handler1)
    let handler2 = (a:number, b:number) =>{}
    hof(handler2)
    let handler3 = (a:number, b:number, c:number) =>{}
    // hof(handler3) //类型“(a: number, b: number, c: number) => void”的参数不能赋给类型“Handler”的参数。
    
    
    //可选参数和剩余参数
    let functionA=(p1:number,p2:number)=>{} //固定参数
    let functionB=(p1?:number,p2?:number)=>{} //可选参数
    let functionC=(...args:number[])=>{} //剩余参数
    
    //1,固定参数可以兼容可选参数和剩余参数
    functionA=functionB //固定参数可以兼容可选参数
    functionA=functionC //固定参数可以兼容剩余参数
    
    //2,可选参数不兼容固定参数和剩余参数
    // functionB = functionA  //不能将类型“undefined”分配给类型“number”
    // functionB = functionC  //不能将类型“undefined”分配给类型“number”
    
    // 可以通过设置 strictFunctionTypes: false来实现兼容
    
     // functionB = functionA
     // functionB = functionC
    //3,剩余参数可以兼容固定参数和可选参数
    functionC = functionA
    functionC = functionB

    2,参数类型

    //2)参数类型
    let handler4 =(a:string) =>{}
    // hof(handler4)  //类型不兼容,不能将类型“number”分配给类型“string”。
    
    interface Point3D{
        x:number;
        y:number;
        z:number;
    }
    interface Point2D{
        x:number;
        y:number;
    }
    let p3d =(point:Point3D) =>{}
    let p2d =(point:Point2D) =>{}
    p3d = p2d; 
    // p2d = p3d; //不兼容 ////Property 'z' is missing in type 'Point2D' but required in type 'Point3D'.
    
    
    //对比接口的兼容性
    let i3d:Point3D = {x:1,y:1,z:1};
    let i2d:Point2D = {x:1,y:1};
    i2d = i3d
    // i3d = i2d //不兼容 //Property 'z' is missing in type 'Point2D' but required in type 'Point3D'.

    3,返回值类型

    //3) 返回值类型
    //目标函数的返回值类型必须与源函数的返回值类型相同或为其子类型
    let rf1 = ()=>({name:"Alice"});
    let rf2 = ()=>({name:"Alice",location:"Beijing"});
    rf1 = rf2;
    // rf2 = rf1; //Property 'location' is missing in type '{ name: string; }' but required in type '{ name: string; location: string; }'.
    
    //函数重载
    
    function overload(a:number,b:number):number
    function overload(a:string,b:string):string
    function overload(a:any,b:any):any {}

    函数重载:

    重载列表中的函数是目标函数,具体实现是源函数,编译器查找重载列表,使用第一个匹配的定义执行执行函数。

    3,枚举的兼容性

    //枚举类型
    //枚举类型和数值类型完全兼容
    enum Fruit {Apple, banana}
    enum Color {Red, Yellow}
    let fruit:Fruit.Apple =4
    
    let no:number = Fruit.Apple
    // let color:Color.Red = Fruit.Apple 枚举类型之间不兼容

    4,类的兼容性

     静态成员和构造函数不参与两个类兼容性比较

    //类的兼容性
    //静态成员和构造函数不参与两个类的兼容性比较
    class A{
        constructor(p:number,q:number){}
        id:number =1;
    }
    
    class B{
        static s =1;
        id:number =2
        constructor(p:number){}
    }
    
    let aa = new A(1,2);
    let bb = new B(1);
    aa = bb;
    bb =aa;

    如果类中有私有成员,两个类就不兼容了

    //类的兼容性
    //静态成员和构造函数不参与两个类的兼容性比较
    class A{
        constructor(p:number,q:number){}
        id:number =1;
        private name:string = ''
    }
    
    class B{
        static s =1;
        id:number =2
        constructor(p:number){}
        private name:string = ''
    }
    
    let aa = new A(1,2);
    let bb = new B(1);
    // aa = bb; //不能将类型“B”分配给类型“A”。类型具有私有属性“name”的单独声明
    // bb =aa; //不能将类型“A”分配给类型“B”。类型具有私有属性“name”的单独声明

    类有私有成员的时候,只有父类和子类直接可以相互兼容

    class A{
        constructor(p:number,q:number){}
        id:number =1;
        private name:string = ''
    }
    
    let aa = new A(1,2);
    
    class AA extends A{
    }
    let aaa = new AA(1,2)
    aa=aaa 
    aaa =aa

    5,泛型的兼容性

    //泛型的兼容性
    interface Empty<T>{
        // value:T //只有类型参数T被接口成员使用了以后才会影响泛型的兼容性
    }
    let intObj1:Empty<number> = {}
    let intObj2:Empty<string> = {}
    intObj1 = intObj2

    泛型函数

    //泛型函数
    //两个泛型函数定义相同,没有指定类型参数,它们之间也可以相互兼容
    let log1 = <T> (x:T):T=>{
        console.log('x');
        return x;
    }
    
    let log2 = <U> (x:U):U=>{
        console.log('y');
        return x;
    }
    log1= log2 

    三、类型保护机制

     因为不知道程序运行时会传入什么参数,所以得在每一处都加上类型断言。

    enum Type {Strong, weak}
    
    class Java{
        helloJava(){
            console.log("hello Java")
        }
    }
    
    class JavaScript{
        helloJavaScript(){
            console.log("Hello JavaScript");
        }
    }
    
    //用类型断言解决报错
    function getLanguage(type:Type){
        let lang = type===Type.Strong?new Java():new JavaScript()
        //创建实例之后运行实例的打印的方法
        if((lang as Java).helloJava){
            (lang as Java).helloJava();
        }else{
            (lang as JavaScript).helloJavaScript()
        }
        return lang
    }
    
    getLanguage(Type.Strong)
    View Code

    代码可读性差,类型保护机制来解决这个问题。

     类型保护:TypeScript能够在特定的区块中保证变量属于某种确定的类型。

    可以在此区块中放心地引用此类型的属性,或者调用此类型的方法。

    4种创建特殊区块的方法。

    1、instanceof

    function getLanguage(type:Type){
        let lang = type===Type.Strong?new Java():new JavaScript()
        // 第一种 instanceof
        if(lang instanceof Java){
            lang.helloJava()
        }else{
            lang.helloJavaScript()
        }
        return lang
    }

    2, in

    判断某个属性是否属于某个对象

    在两个类中分别加入一个属性java和javascript

    enum Type {Strong, weak}
    
    class Java{
        helloJava(){
            console.log("hello Java")
        }
        java :any
    }
    
    class JavaScript{
        helloJavaScript(){
            console.log("Hello JavaScript");
        }
        javascript: any
    }
    function getLanguage(type:Type){
        let lang = type===Type.Strong?new Java():new JavaScript()
        //第二种 in关键字,判断属性是否属于某个对象
        if('java' in lang){
            lang.helloJava()
        }else{
            lang.helloJavaScript()
        }
        return lang
    }

    3, typeof类型保护

    判断基本类型

    function getLanguage(type:Type, x:string | number){
        let lang = type===Type.Strong?new Java():new JavaScript()
        //第三种 typeof 判断基本类型
        //新加函数参数x类型是联合类型string | number
        if(typeof x === 'string'){
            x.length  //调string类型的属性
        }else{
            x.toFixed() //调number类型的方法
        }
        return lang
    }

    4,自定义类型保护函数

    通过创建类型保护函数isJava()判断对象的类型

    function isJava(lang: Java | JavaScript ):lang is Java{
        return (lang as Java).helloJava !== undefined
    }
    
    function getLanguage(type:Type, x:string | number){
        let lang = type===Type.Strong?new Java():new JavaScript()
    
        //第四种 类型保护函数
        if(isJava(lang)){
            lang.helloJava()
        }else{
            lang.helloJavaScript()
        }
    
        return lang
    }
  • 相关阅读:
    andrew ng 学习
    360一些笔试题
    安装visual studio2010提示“Windows Installer 服务不可用”的解决办法
    算法学习从赌钱游戏看PageRank算法
    jQuery Masonry 一个 jQuery动态网格布局的插件
    国内HTML5前端开发框架汇总
    Windows Performance Monitor 学习笔记
    ThinkPad预装win8系统机型安装win7系统的操作指导
    jQuery的Ajax的自动完成功能控件
    JavaScript的Forms验证Parsley.js
  • 原文地址:https://www.cnblogs.com/starof/p/13050710.html
Copyright © 2011-2022 走看看