Typescript高级类型

96 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

类型兼容性

ts具有类型的兼容性 声明一个接口:需要包含一个为name的属性,那么如果class中同样存在name属性

无论说声明一个类或者对象都可以对接口进行正常使用

interface Named {
    name: string;
}

class Person {
    name: string;
}

let p: Named;
p = new Person();
let d:Named
d = {
    name:'222'
}

联合类型解决的问题

function padLeft(value: string, padding: any) {
    if (typeof padding === "number") {
        return Array(padding + 1).join(" ") + value;
    }
    if (typeof padding === "string") {
        return padding + value;
    }
    throw new Error("Expected string or number, got '".concat(padding, "'."));
}
padLeft("Hello world", 123); // ok
padLeft("Hello world", true); // err

对于以上这个例子,我们希望padding可以是number也可以是string类型,所以在定义padding的时候使用了any类型

这样的Ts编译不会出错但是这只是我们预想的传入,如果padding传入的类型是number和string之外的其他类型,那么就会抛错,所以我们应该用联合类型来解决这个问题

function padLeft(value: string, padding: string | number) { // ... }

联合类型的另一种用法

当看到联合类型的这个写法其实有点不太懂,这里的联合不像不同的联合,其实是一种公共类型,getSmallPet中需要符合‘|’前后的俩个接口的公共函数,可以在实例pet中看出来,只用使用了公共的成员ts才不会抛错。

interface Bird { 
    fly(); 
    layEggs();
} 
interface Fish { 
    swim();
    layEggs(); 
} 
function getSmallPet(): Fish | Bird { // ... } 
let pet = getSmallPet(); 
pet.layEggs(); // okay 
pet.swim(); // errors

类型断言的用法

遇到上面这种情况就显得类型断言更加适合 对于实例pet当类型为Fish的时候才去调用swim

let pet = getSmallPet(); 
if ((<Fish>pet).swim) { 
    (<Fish>pet).swim(); 
} 
else { 
    (<Bird>pet).fly();
}

类型保护

但在日常的代码中,可能上面的情况会出现很多,我们可以用类型保护的方法统一将类型断言封装起来,通过返回一个布尔值来进行判断

fucntion isFish(pet:Fish|Bird) pet is Fish{
    retrun (<Fish>).siwm !== undefined
}

return返回一个类型断言进行判断,若不为undefined,则isFish为true

if(isFish(pet)){
    pet.swim()
}else{
    pet.fly()
}