最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • TypeScript学习笔记(六)- 类型推论&类型断言

    正文概述 掘金(转眼岁岁又年年)   2021-01-03   488

    如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。

    类型推论

    let myFavoriteNumber = 'seven';
    myFavoriteNumber = 7;
    // index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
    

    事实上,它等价于:

    let myFavoriteNumber: string = 'seven';
    myFavoriteNumber = 7;
    // index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
    

    如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查:

    let myFavoriteNumber;
    myFavoriteNumber = 'seven';
    myFavoriteNumber = 7;
    

    类型断言

    类型断言(Type Assertion)可以用来手动指定一个值的类型

    类型断言的用途:

    将一个联合类型断言为其中一个类型

    当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型中共有的属性或方法:

    interface Cat {
        name: string;
        run(): void;
    }
    interface Fish {
        name: string;
        swim(): void;
    }
    
    function getName(animal: Cat | Fish) {
        return animal.name;
    }
    

    而有时候,我们确实需要在还不确定类型的时候就访问其中一个类型特有的属性或方法,比如:

    interface Cat {
        name: string;
        run(): void;
    }
    interface Fish {
        name: string;
        swim(): void;
    }
    
    function isFish(animal: Cat | Fish) {
        if (typeof animal.swim === 'function') {
            return true;
        }
        return false;
    }
    
    // index.ts:11:23 - error TS2339: Property 'swim' does not exist on type 'Cat | Fish'.
    //   Property 'swim' does not exist on type 'Cat'.
    

    上面的例子中,获取 animal.swim 的时候会报错。

    此时可以使用类型断言,将 animal 断言成 Fish:

    interface Cat {
        name: string;
        run(): void;
    }
    interface Fish {
        name: string;
        swim(): void;
    }
    
    function isFish(animal: Cat | Fish) {
        if (typeof (animal as Fish).swim === 'function') {
            return true;
        }
        return false;
    }
    

    这样就可以解决访问 animal.swim 时报错的问题了。

    将一个父类断言为更加具体的子类

    当类之间有继承关系时,类型断言也是很常见的:

    class ApiError extends Error {
        code: number = 0;
    }
    class HttpError extends Error {
        statusCode: number = 200;
    }
    
    function isApiError(error: Error) {
        if (typeof (error as ApiError).code === 'number') {
            return true;
        }
        return false;
    }
    

    上面的例子中,我们声明了函数 isApiError,它用来判断传入的参数是不是 ApiError 类型,为了实现这样一个函数,它的参数的类型肯定得是比较抽象的父类 Error,这样的话这个函数就能接受 Error 或它的子类作为参数了。

    但是由于父类 Error 中没有 code 属性,故直接获取 error.code 会报错,需要使用类型断言获取 (error as ApiError).code。

    大家可能会注意到,在这个例子中有一个更合适的方式来判断是不是 ApiError,那就是使用 instanceof:

    class ApiError extends Error {
        code: number = 0;
    }
    class HttpError extends Error {
        statusCode: number = 200;
    }
    
    function isApiError(error: Error) {
        if (error instanceof ApiError) {
            return true;
        }
        return false;
    }
    

    上面的例子中,确实使用 instanceof 更加合适,因为 ApiError 是一个 JavaScript 的类,能够通过 instanceof 来判断 error 是否是它的实例。

    如果是接口,此时就只能用类型断言,通过判断是否存在 code 属性,来判断传入的参数是不是 ApiError 了:

    interface ApiError extends Error {
        code: number;
    }
    interface HttpError extends Error {
        statusCode: number;
    }
    
    function isApiError(error: Error) {
        if (typeof (error as ApiError).code === 'number') {
            return true;
        }
        return false;
    }
    
    将任何一个类型断言为 any
    (window as any).foo = 1;
    
    将 any 断言为一个具体的类型

    类型别名

    type Name = string;
    type NameResolver = () => string;
    type NameOrResolver = Name | NameResolver;
    function getName(n: NameOrResolver): Name {
        if (typeof n === 'string') {
            return n;
        } else {
            return n();
        }
    }
    

    上例中,我们使用 type 创建类型别名。

    类型别名常用于联合类型。

    参考

    TypeScript 入门教程 - ts.xcatliu.com/

    TypeScript 官网 - www.typescriptlang.org/


    起源地下载网 » TypeScript学习笔记(六)- 类型推论&类型断言

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元