• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

TypeScript类型检查机制

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

类型检查机制: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
}

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap