ค้นหาเว็บไซต์

TypeScript - เมธอดโอเวอร์โหลดที่มีโอเปอเรเตอร์สเปรดไม่ถูกจดจำ


ฉันมีคำจำกัดความของคลาสดังต่อไปนี้:

class Test {
  a(msg: string): string;
  a(msg: string, ...args: unknown[]): string | { msg: string, args: unknown[]} {
    if (args) {
      return { msg: msg, args: args };
    }
    return msg;
  }
}

อย่างไรก็ตาม ผมจะได้รับข้อผิดพลาดในการคอมไพล์หากผมทำแบบนี้:

new Test().a("test", "a", 1, 2, 3);

"คาดว่าจะมี 1 อาร์กิวเมนต์ แต่ได้ 5"

ฉันจะโอเวอร์โหลดเมธอดนี้อย่างถูกต้องเพื่อให้มีประเภทค่าที่ส่งกลับต่างกันสำหรับลายเซ็นต่าง ๆ ได้อย่างไร?

คำตอบ #1

การใช้งานฟังก์ชันไม่ใช่ส่วนหนึ่งของการโอเวอร์โหลดทั้งหมดที่มีอยู่ แทนที่จะเป็นเช่นนั้นคุณสามารถเขียนได้ดังนี้:

class Test {
    a(msg: string): string; // overload 1
    a(msg: string, ...args: unknown[]): { msg: string, args: unknown[] } // overload2
    a(msg: string, ...args: unknown[]): string | { msg: string, args: unknown[] } { // impl
       // ...
    }
}
new Test().a("test", "a", 1, 2, 3); // { msg: string; args: unknown[]; }
new Test().a("test") // string

ตัวอย่างสนามเด็กเล่น

คำตอบ #2

TypeScript ไม่สนับสนุนการโอเวอร์โหลดฟังก์ชันด้วยจำนวนพารามิเตอร์ที่แตกต่างกัน

เอกสารระบุว่า:

TypeScript มีแนวคิดของการโอเวอร์โหลดฟังก์ชัน คุณสามารถมีฟังก์ชันหลายฟังก์ชันที่มีชื่อเดียวกันแต่มีชนิดของพารามิเตอร์และชนิดของค่าที่ส่งกลับต่างกัน อย่างไรก็ตาม จำนวนพารามิเตอร์ควรจะเท่ากัน
[...] การโอเวอร์โหลดฟังก์ชันที่มีจำนวนและชนิดของพารามิเตอร์ต่างกันแต่มีชื่อเดียวกันไม่สามารถทำได้

เคล็ดลับหนึ่งในการทำให้สิ่งที่คุณพยายามทำสำเร็จอาจเป็นสิ่งนี้

interface ReturnA {
    msg: string;
    args: any[];
}

class Test {

  a(msg: string, ...args: never[]): string;
  a(msg: string, ...args: any[]): ReturnA
  a(msg: string, ...args: any[]): string | ReturnA {
    if (args) return { msg, args };
    return msg;
  }

}

const t = new Test();

// only 1 param returns string
const str: string = t.a(`a`); 

// two or more params returns the other object type
const obj: ReturnA = t.a(`a`, `param1`);