摸鱼偷学TS:类型兼容性

浅聊一下

周末过的太快了...回来继续学习TS

在金三银四的尾巴上了车,如果你也和我一样也想在大三找一份还不错的实习,欢迎掘友们私聊我交流面经(wechat: LongLBond

类型兼容性

类型兼容性用于确定一个类型是否能赋值给其他类型,这看起来并没有什么太大用处,而实际上当我们了解了兼容性之后才会规避之后实际编程中的很多低级错误

结构类型的兼容性

TS中的类型兼容性是基于结构类型的,结构类型是一种只使用其成员来描述类型的方式,其基本规则是,如果X要兼容Y,那么Y、至少要有与X相同的属性

举个例子:

ts 复制代码
class Person {
    name: string;
    weight: number;
    born: string;
    constructor (weight: number, name: string, born: string) {
        this.name = name;
        this.weight = weight;
        this.born = born;
    }
}
interface Dog {
    name: string;
    weight: number;
}
let dog: Dog
dog = new Person(10, 'wang', '2000')
console.log(dog);//Person { name: 'wang', weight: 10, born: '2000' }

首先,我们定义了一个Person2类,它有三个属性:name(字符串类型)、weight(数字类型)和born(字符串类型)。这个类还有一个构造函数,用于初始化这三个属性。

接着,我们定义了一个Dog接口,它有两个属性:name(字符串类型)和weight(数字类型)。

现在,关键的部分来了。我们声明了一个名为dog的变量,其类型为Dog接口。然后,我们试图使用new Person2(10, 'wang', '2000')来初始化这个dog变量。

简单来说,如果一个对象具有与某个接口相同的属性(名称和类型都匹配),那么这个对象就可以被视为该接口的类型。

函数类型的兼容性

函数类型的兼容性判断要看两个函数的参数,如果X的每个参数在Y中都能找到(名字是否相同不重要,重要的是类型相同), 那么X能赋值给Y

来举个例子:

ts 复制代码
let type1 = (c:number) => 0;
let type2 = (a:number, b:string) => 0;

type1 = type2;//Error
type2 = type1;//ok

观众老爷们看,由于type1中的number类型的参数可以在type2中找到相同类型的参数,虽然他们名字不同但是赋值成功,而将type2赋值给type1的时候由于在type1中找不到对应的string类型的参数,所以赋值失败

来看看报错

如果在函数中出现了可选参数或者rest参数时会怎么样?

ts 复制代码
let type3 = (a:number, b:number) => 0;
let type4 = (a?:number, b?:number) => 0;
let type5 = (...args:number[]) => 0;

type3 = type4;
type4 = type3;//Error

type3 = type5;
type5 = type3;

type4 = type5;//Error
type5 = type4;

来看看报错

我们的可选属性的参数类型可能为undefind,这种情况不能和number兼容

枚举类型的兼容性

枚举与数字类型兼容

ts 复制代码
enum Status {
    x,
    y
}
let s0 = Status.x;
let sum = 1;
s0 = sum;//ok
sum = s0;//ok

类的兼容性

仅仅只有实例成员和方法会相比较,构造函数和静态成员不会被检查:

ts 复制代码
class Ani {
    name: string;
    constructor (name: string, age: number) {
        this.name = name;
    }
    eat() {
        console.log('eat');
    }
}
class Peo {
    name:string;
    constructor (name: string,sex: string) {
        this.name = name;
    }
    eat() {
        console.log('eat');
    }
    
}
let a1: Ani = new Ani('zhangsan',18);
let a2: Peo = new Peo('lisi', 'male');
a1 = a2;//ok
a2 = a1;//ok

在这里只比较了类中的name属性和eat方法,如果他们其中之一不相同的话,就会报错

私有的和受保护的成员必须来自于相同的类:

ts 复制代码
class Ani1 {
    protected name: string;
    constructor (name: string, age: number) {
        this.name = name;
    }
    eat() {
        console.log('eat');
    }
}
class Cat2 extends Ani1 {}

let ani: Ani1 = new Cat2('zhangsan', 18);
let cat = new Cat2('zhangsi',18);

ani = cat;//ok
cat = ani;//ok

class Peo1 {
    protected name:string;
    constructor (name: string,sex: string) {
        this.name = name;
    }
    eat() {
        console.log('eat');
    }
    
}
let a11: Ani1 = new Ani1('zhangsan',18);
let a22: Peo1 = new Peo1('lisi', 'male');
a11 = a22;//error
a22 = a11;//error

泛型的兼容性

泛型本身就是不确定的类型,它的表现根据是否被成员使用而不同.

就比如下面代码

ts 复制代码
interface Person<T> {

}

let x : Person<string>
let y : Person<number>

x = y // ok
y = x // ok

Person接口内没有属性使用了T,所以没有问题

ts 复制代码
interface Person<T> {
    name: T
}

let x : Person<string>
let y : Person<number>

x = y // 不能将类型"Person<number>"分配给类型"Person<string>"。
y = x // 不能将类型"Person<string>"分配给类型"Person<number>"。

name属性使用了T,于是报错

结尾

类型兼容性就到这里了...

相关推荐
最逗前端小白鼠12 分钟前
vue3 数据响应式遇到的问题
前端·vue.js
倚栏听风雨35 分钟前
ts中 ?? 和 || 区别
前端
冴羽40 分钟前
请愿书:Node.js 核心代码不应该包含 AI 代码!
前端·javascript·node.js
我家猫叫佩奇42 分钟前
一款灵感源自《集合啦!动物森友会》的 UI 组件库
前端
mmmmm1234244 分钟前
深入 DOM 查询底层:HTMLCollection 动态原理与 querySelectorAll 静态快照解析
前端·javascript
weixin199701080161 小时前
《TikTok 商品详情页前端性能优化实战》
前端·性能优化
闲坐含香咀翠1 小时前
告别二次登录!Web端检测并唤起Electron客户端实战
前端·客户端
岁月宁静1 小时前
都知道AI大模型能生成文本内容,那你知道大模型是怎样生成文本的吗?
前端·vue.js·人工智能
花间相见2 小时前
【终端效率工具01】—— Yazi:Rust 编写的现代化终端文件管理器,告别繁琐操作
前端·ide·git·rust·极限编程
|晴 天|2 小时前
我如何用Vue 3打造一个现代化个人博客系统(性能提升52%)
前端·javascript·vue.js