Ts:类型断言,泛型

Ts:断言

类型断言兼容
interface Animal {
    name: string;
}
interface Cat {
    name: string;
    run(): void;
}
function testAnimal(animal: Animal) {
    return (animal as Cat);
}
function testCat(cat: Cat) {
    return (cat as Animal);
}
  • 允许 animal as Cat 是因为「父类可以被断言为子类」,就是父类接口类型可以具体为子类。
  • 允许 cat as Animal 是因为既然子类拥有父类的属性和方法,那么被断言为父类,获取父类的属性、调用父类的方法,就不会有任何问题,故「子类可以被断言为父类」,因为子类继承自父类,所以父类的属性方法,子类都可以访问,即具体的子类可以断言为父类

将任何一个类型断言为 any,规避ts校验错误
window.foo = 1; // 临时添加属性,报错,window上没有该属性
(window as any).foo = 1; //  在 any 类型的变量上,访问任何属性都是允许的。它极有可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用 as any

将 any 断言为一个具体的类型,方便后续操作
function getCacheData(key: string): any {
    return (window as any).cache[key];
}
interface Cat {
    name: string;
    run(): void;
}
const tom = getCacheData('tom') as Cat; // 将函数的返回值断言为cat类型
tom.run();

类型断言 vs 类型声明
interface Animal {
    name: string;
}
interface Cat {
    name: string;
    run(): void;
}

const animal: Animal = {
    name: 'tom'
};

// 类型断言
let tom = animal as Cat;  // 正确
------------------------------------
// 类型声明
let tom: Cat = animal; // 报错

它们的核心区别就在于:

  • animal 断言为 Cat,只需要满足 Animal 兼容 Cat 或 Cat 兼容 Animal 即可,即父类断言为具体的子类。
  • animal 赋值给 tom,tom为cat类型,animal为Animal类型,相当于Annimal类型赋值给Cat类型的话,明显是不能赋值的,结构有缺陷。cat的接口类型更具体,所以范围比animal小,所以是animal兼容了cat
    总结就是animal接口包住了cat,cat在animal的基础上扩展了方法,所以cat结构可以声明给animal

类型断言 vs 泛型
通过给 getCacheData 函数添加了一个泛型 ,我们可以更加规范的实现对 getCacheData 返回值的约束,这也同时去除掉了代码中的 any,是最优的一个解决方案。
function getCacheData<T>(key: string): T {
    return (window as any).cache[key];
}
interface Cat {
    name: string;
    run(): void;
}
const tom = getCacheData<Cat>('tom');
tom.run();

泛型 : *泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性*

// 无返回值
function fn4<T>(a: T) {
    console.log(a);
}
fn4(5); // 不指定泛型,自动推论
fn4<string>('23'); // 指定泛型

// 有返回值
function fn5<T>(a: T): T {
    console.log(a);
    return a;
}
泛型--------------多个参数
function fn6<T, K>(a: T, b: K) {
    console.log(a, b);
}
fn6<number, string>(10, '12');
泛型约束,泛型继承接口 ,泛型要满足接口形状
interface inter {
    length: number
}
function fn7<T extends inter>(a: T) {
    // a的类型来自T,T来自inter
    console.log(a.length);
}
泛型接口,定义函数的形状:
interface IG {
    <T>(length: number, arg: T): T;
}

let fn: IG = function <T>(length: number, arg: T): T {
    return arg;
    // return arg + '';
}
泛型类
class CS<T> {
    constructor(public attr: T) { };
    zeroValue: T;
    fn(): T {
        return this.attr;
    }
    // 静态成员不能使用泛型类型
    // static a: T = ''; // Error
}

// 实例化时传入类型值
const cs = new CS<number>(123);

cs.fn(); // 123
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值