typeScript的类型兼容

类型兼容性用于确定一个类型是否能赋值给其他类型。
X兼容Y 即 X(目标类型)= Y(源类型)

1.接口兼容

只要Y具备X接口的属性,则X = Y成立。
这里遵循鸭子类型规则:“如果它走路是鸭子,叫起来也是鸭子,那么它就是鸭子”。鸭子类型指导我们只关注对象的行为,而不关注对象的本身。

interface X{
  a:any;
  b:any;
}
interface Y{
  a:any;
  b:any;
  c:any;
}
let x:X = {a:1,b:2}
let y:Y = {a:1,b:2,c:3}
x = y;
y = x;//类型 "X" 中缺少属性 "c",但类型 "Y" 中需要该属性。
2.函数兼容

2.1 参数个数
目标函数的参数个数要必须要多于源类型参数的个数,参数名不需要相同,参数类型必须一致。

let x = (a: number) => 0;
let y = (b: number, s: string) => 0;
y = x; // OK
x = y; // Error

2.2 固定参数、可选参数、剩余参数
固定参数可以兼容可选参数和剩余参数
可选参数不兼容剩余参数和固定参数
剩余参数可以兼容固定参数和可选参数

let foo = (x: number, y: number) => {};
let bar = (x?: number, y?: number) => {};
let bas = (...args: number[]) => {};
 
foo = bar;
foo = bas;
bar = foo;//Error
bar = bas;//Error
bas = foo;
bas = bar;

2.3 返回值
目标函数的返回值类型必须与源函数的返回值类型相同,或为其子类型。不准确的理解即,源函数≥目标函数,源函数返回参数类型要包含目标函数返回值类型。

interface Point2D {
  x: number;
  y: number;
}
interface Point3D {
  x: number;
  y: number;
  z: number;
}
 
let iMakePoint2D = (): Point2D => ({ x: 0, y: 0 });
let iMakePoint3D = (): Point3D => ({ x: 0, y: 0, z: 0 });
 
iMakePoint2D = iMakePoint3D;
iMakePoint3D = iMakePoint2D; // ERROR: Point2D 不能赋值给 Point3D

其中函数重载兼容性

function overload(a:number,b:number):number;
function overload(a:string,b:string):string;
//前面两条为重载列表,程序运行时会查找第一个匹配的定义去执行函数,后面一条为实现方式
//前为目标函数,后为源类型函数。目标函数的参数要多于源函数的参数
function overload(a:any,b:any):any{};
3.枚举类型

枚举和数字类型相互兼容,不同的枚举类型相互不兼容。

enum Fruit {Apple,Banana}
enum Color {Red , Yellow}
//数字兼容
let fruit :Fruit.Apple = 3;
let no :number = Fruit.Apple ;
//不同枚举类型不兼容
let apple = Fruit.Apple;
apple = Fruit.Banana;
apple = Color.Red;//Error
4.类兼容

4.1 静态成员和构造函数不参与比较,如果两个类具有完全相同的实例成员,则他们完全兼容。

class A{
  static a = 1;//静态成员
  constructor(p:number,q:number){};//构造函数
  id:number = 1;//实例成员
}
class B{
  constructor(p:number){};
  id:number = 2;
}

let aa = new A(1,2);
let bb = new B(1);
aa = bb;
bb = aa;

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

class Animal {
  protected feet: number;
}
class Cat extends Animal {}
 
let animal: Animal;
let cat: Cat;
 
animal = cat; // ok
cat = animal; // ok
 
class Size {
  protected feet: number;
}
 
let size: Size;
 
animal = size; // ERROR
size = animal; // ERROR
5.泛型兼容

5.1 如果两个泛型定义相同,但是没有指定泛型函数参数,它们之间也是相互兼容的。

interface Empty<T>{}

let obj1:Empty<number> = {};
let obj2:Empty<string> = {};
obj1 = obj2;
obj2 = obj1;//Error

5.2 如果泛型中指定了类型参数,会按照结果类型进行比较。

interface Empty<T>{
  value:T//它将在实例化泛型后影响兼容性
}
let obj1:Empty<number> = {value:1};
let obj2:Empty<string> = {value:"你好"};
obj1 = obj2;//Error,不能将类型“Empty<string>”分配给类“Empty<number>”。不能能将类型“string”分配给类型“number”。
obj2 = obj1;//Error
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TypeScript 面试的重点可以包括以下几个方面: 1. TypeScript 的基础知识:了解 TypeScript 的基本语法、类型系统、接口、类、模块等基本概念和用法。 2. 类型注解和类型推断:了解如何使用类型注解来明确变量的类型,以及 TypeScript 如何进行类型推断来推断变量的类型。 3. 类型系统和类型定义:了解 TypeScript类型系统,包括原始类型、联合类型、交叉类型、函数类型、泛型等,以及如何定义自定义类型。 4. 类型兼容性:了解 TypeScript 中的类型兼容性原则,包括结构性类型系统和鸭子类型等。 5. 类型保护和类型断言:了解如何使用类型保护来缩小变量的类型范围,以及如何使用类型断言来手动指定变量的类型。 6. 高级类型:了解 TypeScript 中的高级类型,包括交叉类型、联合类型、条件类型、映射类型等。 7. 模块化开发:了解如何在 TypeScript 中进行模块化开发,包括命名空间和模块的区别,以及如何使用模块加载器进行模块的导入和导出。 8. 工具和生态系统:了解 TypeScript 的相关工具和生态系统,包括使用 TypeScript 编译器将 TypeScript 代码转换为 JavaScript 代码,以及使用第三方库和框架进行 TypeScript 开发。 除了以上的核心知识点,还可以根据具体岗位的需求,加深对 TypeScript 开发实践的了解,例如如何与 React、Node.js、Express 等框架进行集成和开发。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值