1. 程式人生 > 其它 >ts筆記-型別相容性

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
常用網站: SegmentFault | GitHub | 掘金社群