TypeScript实例讲解(二十七)

320 阅读2分钟

这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战

接上一篇:TypeScript实例讲解(二十六)

本篇内容:TypeScript 类型断言。

类型断言

类型断言(Type Assertion)的作用是手动指定一个值的类型。

语法:值 as 类型 或者 <类型>值

// 例 1
function getLength(name: string | number) {
    return name.length;
}

报错:Property 'length' does not exist on type 'string | number'。

报错的原因是参数 name 的值可能是 number 类型,number 类型的值不存在 length 属性,这种情况则需要我们采用类型断言来处理。

语法一:<>

// 例 2
function getLength(name: string | number) {
    return (<string>name).length;
}
console.log(getLength('abc'));  // 3
console.log(getLength(20));     // undefined

语法二:as

// 例 3
function getLength(name: string | number) {
    return (name as string).length;
}

语法二的结果和语法一的结果一致。

类型断言只在编译阶段起作用,类型断言语句在编译结果中会被移除。因此它不是类型转换,不会真的影响到变量的类型。

把一个联合类型断言为其中一个类型。

有时候,我们确实需要在还不确定类型的时候就访问其中一个类型特有的属性或方法,比如:通过类型断言的方式实现类型保护。

// 例 4
// 声明 interface
interface Teacher {
    name: string;
    profession: 'teacher';
    teach: () => {};
}
interface Dancer {
    name: string;
    profession: 'dancer';
    dance: () => {};
}

function work(person: Teacher | Dancer) {
    if (person.profession === 'teacher') {
        // 如果person的职业是教师,我们就通过断言的方式告诉TypeScript person就是教师
        (person as Teacher).teach()
    } else {
        (person as Dancer).dance()
    }
}
把一个父类断言为更加具体的子类
// 例 5
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;
}

例5中有一个更合适的方式来判断是不是 ApiError,那就是使用 instanceof。

把任何一个类型断言为 any
// 例 6
window.name = 'xxx';

有时候需要在 window 上添加一个属性,如 name,但 TypeScript 编译时会报错:Property 'name' does not exist on type 'Window'。

提示 window 上不存在 name 属性,此时我们就可以使用 as any 临时将 window 断言为 any 类型:

// 例 7
(window as any).name = 'xxx';

把类型断言为 any 的确有一定的作用,但特别要注意不能滥用。

注意事项

类型断言只能够通过编译器的检查,无法避免运行时的错误,因此在开发时如果滥用类型断言可能会导致运行时错误。
因为 jsx 语法包括尖括号<>,TypeScript 在 .tsx 文件里禁用了使用尖括号的类型断言,类型断言使用 as 语法。

本篇完!如果文章对你有一点点帮助,请记得点个赞哦。