Byte Ebi's Logo

Byte Ebi 🍤

每天一小口,蝦米變鯨魚

TypeScript 的 Class 及 Interface

TypeScript 的 Class 及 Interface 與語法範例

Ray

介紹 TypeScript 的 Class 和 Interface 基本概念
包含 Class 的實踐與介面繼承的範例

Interface 介面

定義任意結構或型別

基本定義

interface publicPoint {
  w?: number,  // 選用屬性不一定要在最後
  x: number | string,
  y: number,
}

// 介面可以合併,但不能複寫已定義的屬性
interface publicPoint {
  z: number,
}

// 繼承屬性
interface Point1 extent publicPoint {
  a?:number
}

interface Point2 extent publicPoint {
  b: string,
  c: string
}

interface privatePoint {
  d: number,
}

// 同時繼承多個 interface
interface Point3 extents publicPoint, privatePoint {
  e: number
}

const myPoint1: Point1 = {x: 0, y: 0, z: 0}
const myPoint2: Point2 = {x: 0, y: 0, z: 0, b:'oh', c:'nyo'}
const myPoint4: Point3 = {x: 0, y: 0, z: 0, d:0, e:0}

函數定義

interface Func {
  (num1: number, num2: number): number;
}

const addFunc: Func = (arg1, arg2) => arg1 + arg2;

索引類型

定義成索引類型後,原先傳入的陣列將不能使用陣列原型鏈上的方法將不存在 例如:呼叫 role1.length 會報錯

interface Role {
  [id: number]: string;
}

const role1: Role = ["admin", "user"];
const role2: Role = {
  0: "admin",
  1: "user",
  5: "author",
};

迴避多餘屬性檢查

有時候在使用 interface 時會多傳入其他參數,此時會因為有多餘屬性而報錯 有三個方法可以迴避多餘屬性檢查(Excess Property Checks)

1. 型別斷言(type assertion)

interface MyType {
  color: string;
}

const getColor = (myType: Mytype) => {
  return `${myType.color}`;
};

getColor({
  color: "yellow",
  type: "color",
  num: 0,
} as MyType); // 聲明他就是一個 myType 型別

2. 索引簽名(index signature)

比較推薦的做法

interface MyType {
  color: string;
  [prop: string]: any; // 接受額外的屬性
}

const getColor = (myType: Mytype) => {
  return `${myType.color}`;
};

getColor({
  color: "yellow",
  type: "color",
  num: 0,
  group: [],
  skill: () => {},
});

3. 類型兼容

不推薦的方式

interface MyType {
  color: string;
}

// 只解構出需要的索引
const getColor = ({ color }: Mytype) => {
  return `${color}`;
};

const option = { color: "yellow", size: 12 };
getColor(option);

Class 類別

class Person {
  name = "Rui"; // 預設 public

  private age = 30; // 私有屬性
  getAge() {
    return this.age;
  }
}

const person = new Person();

// 繼承
class Person1 extends Person {
  // 物件被 new 的時候會第一步執行構造函數,沒寫也會自動執行
  constructor() {
    super(); // 呼叫父類別,有寫 constructor 就一定要呼叫

    console.log(super.getAge()); // 執行父類別的方法
    console.log(this.getAge()); // 執行覆寫後的類別方法
  }

  // 子類別會覆寫父類別
  getAge() {
    return 18;
  }
}

const person1 = new Person1();

Class 實踐介面

interface FoodInterface {
  type: string;
}

class ChineseFoodClass implements FoodInterface {
  constructor(public type: string) {}
}

// 等同於

class JapaneseFoodClass implements FoodInterface {
  type: string;
  constructor(arg: string) {
    this.type = arg;
  }
}

介面繼承 Class

介面會繼承類型,但不包含實踐 介面會繼承 private 和 protected 屬性,但只能由 Class 本身或其子類別實作

class Person {
  protected name = "Rui";
  private nickName = "Ray";

  getName() {
    return this.name + this.nickName;
  }
}

interface I extends Person {}

// 類別與類別,介面與介面之前使用 extends
// 類別與介面使用 implements
class C extends Person implements I {
  getName() {
    return this.name + " new Class C";
  }
}

const newInstance = new C();
console.log(newInstance.getName());
// Rui new Class C

最新文章

Category

Tag