前面讲类型断言时,提到可以通过断言 as 将联合类型断言为某一具体类型进而访问其存在的属性,但这样每次访问都需要进行断言且有风险:
function getCount(data: any[] | Set<any>): Number {if (Object.prototype.toString.call(data) === "[object Array]") {// ERROR: 类型“any[] | Set<any>”上不存在属性“length”。类型“Set<any>”上不存在属性“length”return data.length;}// ERROR: 类型“any[] | Set<any>”上不存在属性“size”。类型“any[]”上不存在属性“size”return data.size;}
使用断言解决
function getCount(data: any[] | Set<any>): Number {if (Object.prototype.toString.call(data) === "[object Array]") {return (data as Array<any>).length;}return (data as Set<any>).size;}
使用条件判断
如 in instanceof Array.isArray 等判断条件,为真后自然能访问其属性:
function getCount(data: any[] | Set<any>): Number {if ('length' in data) {return data.length;}return data.size;}
使用类型谓词 is
一般用于函数返回值类型中,判断参数是否属于某一类型,并根据结果返回对应的布尔类型。它不仅返回函数运行结果到判断条件中,还返回结果类型到条件块中。
function isArray(u: any): u is Array<any> {return Object.prototype.toString.call(u) === "[object Array]";}function getCount(data: any[] | Set<any>): Number {if (isArray(data)) {return data.length;}return data.size;}
你可能会发现前面使用断言或条件判断还比使用类型谓词 is 更加简单(少些一个函数),但当要判断的联合类型不止两个子类型时,类型谓词 is 的优势就出现了:
- 比断言更安全
- 不用每处都编写特定的条件判断,可用泛型函数解决:
