跳到主要内容

类型保护

2023年03月02日
柏拉文
越努力,越幸运

联合类型非常适合这样的情形,可接收的值有不同的类型TypeA类|TypeB类。 当我们想明确地知道是否拿到TypeA类型中的属性或者方法时会怎么做? 补充:联合类型只能访问联合类型的所有类型中共有的成员,如果访问非共有成员,会报错!

联合类型中错误且不优雅逻辑
interface TypeA {
say:()=>{}
}

interface TypeB{
run:()=>{}
}

function foo(argu: TypeA | TypeB){
argu.say(); // TypeScript 报错:Property 'say' does not exist on type 'TypeA | TypeB'. Property 'say' does not exist on type 'TypeB'.ts(2339)
}

方式一: 通过类型断言区分类型、保护类型

联合类型中 通过 类型断言 来区分类型、保护类型
interface TypeA {
say:()=>{}
}

interface TypeB{
run:()=>{}
}

function foo1(argu: TypeA | TypeB){
(argu as TypeA).say(); // 通过 as 类型断言,进而区分类型,保护类型
}

function foo2(argu: TypeA | TypeB){
(<TypeA>argu).say(); // 通过 <> 类型断言,进而区分类型,保护类型
}

方式二: 通过 in 区分类型、保护类型

interface TypeA {
name: string,
say():void
}

interface TypeB {
name: string
run():void
}


function foo1(argu: TypeA | TypeB) {
if('say' in argu){
argu.say();
}
}

方式三: 通过 typeof 区分类型、保护类型

错误且不优雅逻辑
function foo1(x:string|number,y:string|number) {
return x+y; // TypeScript 报错: Operator '+' cannot be applied to types 'string | number' and 'string | number'.ts(2365)
}
通过 typeof 进行逻辑判断来区分类型、保护类型
function foo1(x:string|number,y:string|number) {
if(typeof x === 'string' || typeof y === 'string'){
return `${x}${y}`;
}else{
return x+y;
}
}

方式四: 通过 keyof 区分类型、保护类型

通过 keyof 区分类型、保护类型
interface MapType {
id: number;
label: string;
value: number;
}

function foo<T extends keyof MapType>(key: T): MapType[T] {
const map = {
id:1,
label:'哈哈',
value:11
}
return map[key];
}

console.log(foo('label'));

方式五: 通过 instanceof 区分类型、保护类型

错误且不优雅逻辑
class Foo {
num: number;
constructor(num:number){
this.num = num;
}
}

function foo1(x: object | Foo, y: object | Foo) {
return x.num + y.num; // TypeScript 报错 Property 'num' does not exist on type 'object | Foo'. Property 'num' does not exist on type 'object'.ts(2339)
}
通过 instanceof 进行逻辑判断来区分类型、保护类型
class Foo {
num: number;
constructor(num:number){
this.num = num;
}
}

function foo1(x: object | Foo, y: object | Foo) {
if(x instanceof Foo && y instanceof Foo){
return x.num + y.num;
}
}