TS 是结构类型系统(structural type system),基于结构/形状检查类型,而非类型的名字。

TS 中的兼容性,主要看结构是否兼容。(核心是考虑安全性),结构化的类型系统(又称鸭子类型检查),如两个类型名字不一样但是无法区分

类型兼容性是基于结构子类型的。 结构类型是一种只使用其成员来描述类型的方式。

如果x要兼容y,那么y至少具有与x相同的属性。

这里要检查y是否能赋值给x,编译器检查x中的每个属性,看是否能在y中也找到对应属性。

X 兼容 Y:X(目标类型)= Y(源类型)

简单一句话概括兼容性: 重新赋值不报错(类型自动转化)

一.基本数据类型的兼容性

let temp: string | number;
let num!: number;
temp = num;
let obj: {
toString(): string;
};
let str: string = "yya";
obj = str; // 字符串中具备toString()方法,所以可以进行兼容
obj.toString(); // 安全, 保证使用的时候不会发生异常

二.接口兼容性

接口的兼容性,只要满足接口中所需要的类型即可!(保证你要的,我都有,就行,多了也没关系)

interface IAnimal {
name: string;
age: number;
}
interface IPerson {
name: string;
age: number;
address: string;
}
let animal: IAnimal;
let person: IPerson = {
name: "yya",
age: 18,
address: "beijing",
}; type T2 = IPerson extends IAnimal ? true : false; // true
animal = person; // 子类赋予给父类 兼容

三.函数的兼容性

函数的兼容性主要是比较参数和返回值

参数:赋值函数的参数要少于等于被赋值的函数:也就是说,对应函数的参数来讲,少的参数可以赋予给多的,因为内部实现传了多个可以少用或不用(忽略额外的参数在 JavaScript 里是很常见的)

sum2的每个参数必须能在sum1里找到对应类型的参数。 注意的是参数的名字相同与否无所谓,只看它们的类型sum2的每个参数在sum1中都能找到对应的参数,所以允许赋值。

let sum1 = (a: string, b: string) => a + b;
let sum2 = (a: string) => a;
sum1 = sum2;

举例: Array#forEach给回调函数传 3 个参数:item,index 和 array。 尽管如此,传入一个只使用第一个参数的回调函数也是可以的

type Func<T> = (item: T, index: number, array: any[]) => void;
function forEach<T>(arr: T[], cb: Func<T>) {
for (let i = 0; i < arr.length; i++) {
cb(arr[i], i, arr);
}
}
forEach([1, 2, 3], (item) => {
console.log(item);
});

返回值:

type sum1 = () => string | number;
type sum2 = () => string; let fn1: sum1;
let fn2!: sum2;
fn1 = fn2;

四.类的兼容性

类与对象字面量和接口差不多,但有一点不同:类有静态部分和实例部分的类型。 比较两个类类型的对象时,只有实例的成员会被比较。 静态成员和构造函数不在比较的范围内。

class Animal {
feet!: number;
constructor(name: string, numFeet: number) {}
} class Size {
feet!: number;
constructor(numFeet: number) {}
} let a!: Animal;
let s!: Size; a = s; // OK
s = a; // OK

类的私有成员和受保护成员

只要有 private 或者 protected 关键字会影响兼容性, 当检查类实例的兼容时,如果目标类型包含一个 private 私有成员,那么源类型必须包含来自同一个类的这个私有成员。 这条规则也适用于包含 protected 受保护成员实例的类型检查。 允许子类赋值给父类,但是不能赋值给其它有同样类型的类。

class A {
private name!: string;
age!: number;
} class B {
private name!: string;
age!: number;
} // let a: A = new B(); // error class Parent {
protected name: string = "zf";
age: number = 11;
}
class Child extends Parent {}
let child: Parent = new Child(); // ok

五.泛型的兼容性

泛型比较的是最终的结果 比较的不是泛型传递的参数

例一:

interface Empty<T> {}

let x: Empty<number>;
let y!: Empty<string>; type xx = Empty<number> extends Empty<string> ? true : false; // true x = y; // OK 因为 y 匹配 x 的结构

在例一中,x 和 y 是兼容的,因为它们的结构使用类型参数时并没有什么不同。 把这个例子改变一下,增加一个成员,就能看出是如何工作的了:

例二:

interface NotEmpty<T> {
data: T;
}
let x: NotEmpty<number>;
let y: NotEmpty<string>; type xx = NotEmpty<number> extends NotEmpty<string> ? true : false; // false x = y; // Error, 不兼容

对于没指定泛型类型的泛型参数时,会把所有泛型参数当成 any 比较。 然后用结果类型进行比较,就像例一:

let identity = function <T>(x: T): T {};

let reverse = function <U>(y: U): U {};

identity = reverse; // OK,  (x: any) => any 匹配 (y: any) => any

六.枚举的兼容性

枚举类型与数字类型兼容,并且数字类型与枚举类型兼容

enum Status {
Pending,
Resolved,
Rejected,
} let current = Status.Pending;
let num = 0; current = num;
num = current;

不同枚举类型之间是不兼容的。

enum Status {
Pending,
Resolved,
Rejected,
}
enum Color {
Red,
Blue,
Green,
} let current = Status.Pending;
let color = Color.Red; current = color; // 不能将类型“Color.Red”分配给类型“Status”

标称类型简短介绍

类型分为两种 结构化类型(structural type system) 、标称类型(nominal type system)

标称类型: 虽然 BTC,USDT 都是 number 类型,但还是想要用不同的类型表示,且不能互换,数据的值本身没什么区别,安上不同名字就是不同类型,也就是说,标称类型系统中,两个变量是否类型兼容(可以交换赋值)取决于这两个变量显式声明的类型名字是否相同。

class AddType<S> {
private _type!: S;
}
type NewType<T, S extends string> = T & AddType<S>; type BTC = NewType<number, "btc">; // number + BTC
type USDT = NewType<number, "usdt">; // number + USDT
let btc = 100 as BTC;
let usdt = 100 as USDT; function getCount(count: USDT) {
return count;
}
getCount(usdt);

TypeScript 学习笔记 — 类型兼容 (十)的更多相关文章

  1. Typescript 学习笔记三:函数

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  2. 【Java学习笔记之二十六】深入理解Java匿名内部类

    在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意 ...

  3. Typescript 学习笔记七:泛型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  4. Typescript 学习笔记六:接口

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  5. Typescript 学习笔记五:类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  6. Typescript 学习笔记二:数据类型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  7. Typescript 学习笔记一:介绍、安装、编译

    前言 整理了一下 Typescript 的学习笔记,方便后期遗忘某个知识点的时候,快速回忆. 为了避免凌乱,用 gitbook 结合 marketdown 整理的. github地址是:ts-gitb ...

  8. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十二章:四元数(QUATERNIONS)

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十二章:四元数(QUATERNIONS) 学习目标 回顾复数,以及 ...

  9. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图 代码工程地址: https://github.c ...

  10. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十六章:实例化和截头锥体裁切

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十六章:实例化和截头锥体裁切 代码工程地址: https://git ...

随机推荐

  1. MFC调用外部dll时,出现无法解析的外部符号的解决方法)

    最近在一个MFC工程文件中调用了多个dll和lib文件,包括matlab和can连接文件,时常出现"无法解析的外部符号"的错误,特此记录解决方法.   通常出现这个问题的原因有以下 ...

  2. 【RTOS】《多任务抢占式调度器》笔记

    <多任务抢占式调度器>读书笔记 1.多任务系统 在多任务调度器的作用下,多个任务轮流使用cpu,实现多任务相互独立并发运行的效果,能够充分利用硬件资源,提高cpu效率 2.任务特性 a.动 ...

  3. nodejs中的kafkajs,消费顺序,不重复消费

    参考:https://kafka.js.org/docs 确保同一个消息发送到同一个partition,一个topic,一个partition,一个consumer,内部单线程消费1.封装kafkaU ...

  4. Tomcat put 漏洞批量工具

    工具下载 https://share.weiyun.com/96ffd3bf26b09ffece8d01317f3b3efb

  5. Maven常用参数及其说明

    Maven常用参数及其说明 -h,--help Display help information-am,--also-make 构建指定模块,同时构建指定模块依赖的其他模块;-amd,--also-m ...

  6. bootstrapTable insertRow 新增行保留原数据

    思路:保留原数据,然后新增行. var optionsxx = {//省略xxx: columns: [{ checkbox: true}, { field: 'id', title: '主键', c ...

  7. 项目自动备份,oracle 自动备份

    1 项目备份      变量的形式 定时任务不执行就都写成了绝对路径 #!/bin/bash # # 项目路径 /usr/local/tomcat-bjkjdx 备份文件路径/usr/local/ba ...

  8. Leetcode457

    A very absurd description for this problem, but people can get the idea by looking at the examples.. ...

  9. 蓝桥2020 B组 第一场考试

    2. 纪念日 问题描述: 请问从 1921 年 7 月 23 日中午 12 时到 2020 年 7 月 1 日中午 12 时一共包 含多少分钟? 答案提交: 这是一道结果填空题,你只需要算出结果后提交 ...

  10. java初学者-向一个长度为5的整型数组中随机生成5个1-10的随机整数 ,要求生成的数字中没有重复数

    public static void main(String[]args){ //定义一个数组 长度为5:角标为4 int []arr=new int[5]; for(int i=0;i<5;i ...