likes
comments
collection
share

【TypeScript】TS类型断言-类型的声明和转换(七)

作者站长头像
站长
· 阅读数 18

前言

为什么要有断言这个概念?TS中并不能判断在使用联合类型时具体是那种类型?当我们不知道是什么类型的情况下要使用某个类型特有的属性或者方法,那么就可以用断言来实现,它实际上是对编辑器做了提前告知的行为,但是并不能保证运行中报错。主要有两种方式来实现,具体如下:

断言形式

(1)尖括号形式

语法:<type>+value,尖括号中填写具体的类型。

//anyValue是any类型,在使用时候将其断言为string类型
let anyValue:any = 'zhangsan';
let length:number = (<string>anyValue).length;//0
//anyValue是string或者number联合类型,在使用时候将其断言为string类型
let anyValue:string | number = 'zhangsan';
let length:number = (<string>anyValue).length;//0

使用断言虽然能避免编译中的报错,但是却避免不了运行中的报错

type ClaaM = number | string;
function func(val:ClaaM):string{
   return  (<string>val).substr(0,1)
}
func(1)

我们可以看到编辑器中没有报错,如下: 【TypeScript】TS类型断言-类型的声明和转换(七) 但是编译成JS后,运行过程中就报错了,如下: 【TypeScript】TS类型断言-类型的声明和转换(七) 所以除非确切的知道变量的数据类型,否则不要使用类型断言,这是因为类型断言会让 TypeScript 编译器将变量当做指定的类型,而不管它实际的类型,在程序运行时可能有类型错误,断言需要慎用

(2)as形式(推荐)

语法:value as type,as后跟具体类型。

let anyValue:any = 'zhangsan';
let length:number = (anyValue as string).length;//0

断言类型

(1)非空断言

含义:非空断言用!表示,它用来断定某变量一定不是 nullundefined。 如果不做非空判断则会直接报错,具体如下:

type ClassTime = () => number;
const start = (ClassTime: ClassTime | undefined | null)=> {
        let time = ClassTime(); 
}

【TypeScript】TS类型断言-类型的声明和转换(七)

做了非空断言,则报错信息就没有了,函数在执行的时候会忽略undefined、null.

type ClassTime = () => number;
const start = (ClassTime: ClassTime | undefined | null) {
        let time = ClassTime!(); 
}

这里出一个面试题,如下:

// 面试题  
const a: number | undefined = undefined;
const b: number = a!;//这里使用断言无效,a已经有明确的值
console.log(b);
// 上面的代码会编译成
const a = undefined;
const b = a;
console.log(b); // undefined

注意:只有在strictNullChecks开启时,TS才会报错,怎么开启呢?以VScode编辑器为例

  • 点击设置按钮后,选择设置选项 【TypeScript】TS类型断言-类型的声明和转换(七)
  • 搜索strictNullChecks,然后勾选下面的选项就可以啦 【TypeScript】TS类型断言-类型的声明和转换(七)

(2)肯定断言-肯定化保证赋值

含义:允许在实例属性或者变量声明后面放置一个 !号,从而告诉 TS该属性会被明确地赋值。 错误示范,我们在对变量赋值之前就使用变量,就会报错。

let score: number;
startClass();
console.log('' + score); // 使用前赋值
function startClass() {
    score = 5;
}

编辑器中会直接报错,如图所示: 【TypeScript】TS类型断言-类型的声明和转换(七) 怎么避免这种现象呢?我们可以在变量声明的时候就告诉编辑器该属性一定会被赋值,即在变量名后面加个!符号

let score!: number;
startClass();
console.log('' + score); // 使用前赋值
function startClass() {
    score = 5;
}

(3)将任何类型断言为any

为什么会有这种需求呢?比如以下案例:我们知道obj一定是有值的,请求接口后赋值给obj,所以一定是有值的,但是我们直接赋值,就会报错

const obj = {};
obj.name = 'zhangsan';
obj.age = 19;

【TypeScript】TS类型断言-类型的声明和转换(七) 我们可以改成这样就不会报错啦

const obj:Object = {};
(<any>obj).name = 'zhangsan';
(<any>obj).age = 19;

(4)调用函数时将参数和返回值断言成精确的值


function func(val:any):any{
    return 1
}
func(1)

调用函数时我们改成以下所示,这样方便我们维护代码,约束了传参和函数返回值,不能any走天下。

let data = <number>func(<string>'zhangsan')

编译成JS如下

function func(val) {
    return 1;
}
var data = func('zhangsan');