Day20 :【TypeScript 學起來】是 JavaScript 沒有的 Function Overloads(函式超載)

終於20天了,那個心情就是有點開心快結束了,但對後面10篇感到擔憂,既期待又怕無法完賽 XDD

好啦,講完廢話,今天要來講 Function Overloads, 接觸到這個功能覺得 cool, JavaScript 絕對不能這麼做, 因為會有 hoisting 現象。讓我們看下去~

若有錯誤,歡迎留言指教,感恩的心。


Function Overloads 函式超載

函式超載指的是擴充一個函式可以被執行的形式。簡單來說就是針對同一個 function 提供多個不同的 type definition。可以使用相同的 function 名稱,定義不同的參數數量或型別創建多種方法。

Function Overload 會包含兩個部分:

  • overload signatures:也就是 type definition 的部分, 通常會定義2種或以上。
  • function implementation:實際上執行的 function,它的型別需要滿足所有的 overload signatures。

例子1:

如下面例子, padding function (設定 css 的 padding)你要傳入的參數, 有可能是1 個,2 個或 4 個, 我們就可以使用 Function Overloads 來進行約束。像這個例子如果不小心帶入 3 個參數則會提醒 No overload expects 3 arguments

// overload signatures 定義
function padding(all: number): object;
function padding(topAndBottom: number, leftAndRight: number): object;
function padding(top: number, right: number, bottom: number, left: number): object;

// function implementation 實際執行的function
function padding(a: number, b?: number, c?: number, d?: number) {
  if (b === undefined && c === undefined && d === undefined) {
    b = c = d = a;
  } else if (c === undefined && d === undefined) {
    c = a;
    d = b;
  }
  return {
    top: a,
    right: b,
    bottom: c,
    left: d
  };
}

padding(1); // ok: all
padding(1, 1); // ok: topAndBottom, leftAndRight
padding(1, 1, 1, 1); // ok: top, right, bottom, left
padding(1, 1, 1); // Error: No overload expects 3 arguments, but overloads do exist that expect either 2 or 4 

以這個例子, 我們可以看到 compiler 會標記有 +2 overloads,他會自動偵測到你在使用 function overloads,蠻 cool 的。

例子2:

//overload signatures
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;

//function implementation
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d);
  } else {
    return new Date(mOrTimestamp);
  }
}
const d1 = makeDate(12345678); //ok
const d2 = makeDate(5, 5, 5); //ok
const d3 = makeDate(1, 3); //error: No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.

使用上要注意的地方

1. 要至少2個或以上的 overload signatures

❌ 以下範例, 他預期不帶參數執行 fn(); 會印出 "hello",但結果報錯,因為只有定義會帶入x: string,會帶入1個參數,結果沒有帶入參數所以報錯提醒。

function fn(x: string): void;
function fn() {
   console.log("hello");
}
fn(); //error: Expected 1 arguments, but got 0.

✅ 再加入無參數的 overload signatures 即可。

function fn(x: string): void;
function fn(): void;
function fn() {
  console.log("hello");
}
fn();

2. 實際執行函式帶入的參數型別要兼容 overload signatures 的型別

❌ 在實際執行函式帶入的參數型別只有 boolean, 第二個 overload signatures 的參數型別為string, 就與執行函式參數無法兼容。

//overload signatures 
function fn(x: boolean): void;

function fn(x: string): void; //error:This overload signature is not compatible with its implementation signature. 

//function implementation 執行函式
function fn(x: boolean) {
    console.log("hello");
}

✅ 如果要兼容的話, 就使用聯合型別 union type 即可。

function fn(x: boolean): void;
function fn(x: string): void;

function fn(x: boolean | string) {
  console.log("hello");
}

fn(""); //"hello"

下一篇要來筆記 Generic 泛型, 明天見!


參考資料

https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads
https://pjchender.dev/typescript/ts-functions/#function-overload%E5%87%BD%E5%BC%8F%E8%B6%85%E8%BC%89
https://basarat.gitbook.io/typescript/type-system/functions#overloading

Leave a Comment

Your email address will not be published. Required fields are marked *

ZH-TW EN ES