ts笔记-类型兼容性

类型兼容性用于确定一个类型是否能赋值给其他类型。

any

任何类型都能被赋值给any

let foo: any = 123;
foo = 'hello';

结构化

TypeScript 对象是一种结构类型,因此只要结构匹配就是兼容的

interface Point1 {
    x: number;
    y: number;
  }
  
  class Point2D {
    constructor(public x: number, public y: number) {}
  }

// OK Point2D: {x: 1, y: 2}
let p1: Point1 = new Point2D(1,2)

结构化数据如果包含原数据,也是可行的

interface Point2D {
  x: number;
  y: number;
}

interface Point3D {
  x: number;
  y: number;
  z: number;
}

const point2D: Point2D = { x: 0, y: 10 };
const point3D: Point3D = { x: 0, y: 10, z: 20 };

function PointFn(point: Point2D) {
  /* do something */
}

//  额外的信息,没关系
PointFn(point3D)

// 缺少信息,不行
PointFn({x: 1})

函数

返回类型如果包含更多的数据,函数是兼容的

interface Point2D {
    x: number;
    y: number;
  }
  interface Point3D {
    x: number;
    y: number;
    z: number;
  }



  let f1 = (): Point2D => ({x: 1, y: 2})

  let f2 = (): Point3D => ({x: 1, y: 2, z: 3})

  // OK, f2包含更多的数据
  f1 = f2

  // ERROR
  f2 = f1

函数的参数如果少于定义的类型,函数参数是兼容的

// f1接受一个callback函数,callback函数接收两个参数,无返回值
const f1 = (x: (err: any, data: any) => void) => {}

// OK
f1((err) => null)

// OK
f1(() => null)


// ERROR
f1((err, data, more) => null)

可选参数、确定参数和rest参数互相兼容

let f1 = (x: number, y: number) => {}

let f2 = (...args: number[]) => {}

let f3 = (x?: number, y?: number) => {}

f1 = f2 = f3

f3 = f2 = f1

f1 = f3 = f2

枚举

枚举与数字类型相互兼容

enum Status {
  Ready,
  Waiting
}

let status = Status.Ready;
let num = 0;

status = num;
num = status;

不同枚举的枚举变量是不兼容的

enum Status {
  Ready,
  Waiting
}
enum Color {
  Red,
  Blue,
  Green
}

let status = Status.Ready;
let color = Color.Red;

status = color; // Error

构造函数和静态成员不会被检查

class Animal {
  feet: number;
  constructor(name: string, numFeet: number) {}
}

class Size {
  feet: number;
  constructor(meters: number) {}
}

let a: Animal = new Animal('wmui', 18);
let s: Size = new Size(18);


a = s; // OK
s = a; // OK

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

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

泛型

当类型参数被内部成员使用时,会影响兼容性

interface Empty<T> {
  data: T;
}

let x: Empty<number>;
let y: Empty<string>;

x = y; // Error

当类型参数没有被内部使用时,不存在兼容性问题

interface Empty<T> {}

let x: Empty<number>;
let y: Empty<string>;

x = y; // ok

如果尚未实例化泛型参数,则在检查兼容性之前将其替换为 any

父类兼容子类,子类不兼容父类


class List<T> {
  add(val: T) {}
}

class Animal {
  name: string;
}
class Cat extends Animal {
  meow() {
    // ..
  }
}
// 父类兼容子类
const animals = new List<Animal>();
animals.add(new Animal()); // ok
animals.add(new Cat()); // ok

// 子类不兼容父类
const cats = new List<Cat>();
cats.add(new Animal()); // Error
cats.add(new Cat()); // ok
上一篇:数据库表中多对多关系怎么设计?


下一篇:ts学习笔记三:函数的使用