Typescript เลือกเฉพาะเมธอดบางอย่างจาก overload (เพื่อส่งไปยัง Parameters<T>)
พื้นหลัง
ดังนั้นฉันมีปัญหาในการดึงพารามิเตอร์เฉพาะจากฟังก์ชันที่ถูกโอเวอร์โหลด ตัวอย่างเช่น:
// someLib.d.ts
type Component<T> = {};
type A = {};
type B = {};
type C = {};
type Opts = {};
type ModernOpts = {};
export declare function mount(component: A, options: Opts): Component<A>;
export declare function mount(component: B, options: Opts): Component<B>;
export declare function mount(component: C, options: ModernOpts): Component<C>;
ปัญหาคือ ไม่ว่าอย่างไรถ้าฉันทำสิ่งนี้กับไฟล์อื่น:
import { mount } from 'someLib';
type specificMountParams = Parameters<typeof mount>;
พารามิเตอร์ที่ฉันได้รับคือ [C, ModernOpts] และดูเหมือนว่าจะไม่มีวิธีใดในการรับพารามิเตอร์ของ [A, Opts] หรือ [B, Opts]
คำถาม
มีวิธีใดบ้างที่จะดึงพารามิเตอร์ เฉพาะ จากฟังก์ชันที่มีการโอเวอร์โหลด? (เพื่อที่ฉันจะได้พารามิเตอร์ [A, Opts])
ข้อจำกัดและข้อมูล
ประเภทเหล่านั้น (A, B, Opts) ไม่ได้ถูกส่งออกโดยไลบรารี และฉันจำเป็นต้องสร้างฟังก์ชันที่ต้องใช้ประเภทดังกล่าวเพื่อทำสิ่งที่คล้ายกัน
คำตอบ #1
จากเอกสาร:
เมื่อทำการอนุมานจากชนิดที่มีหลายลายเซ็นการเรียก (เช่น ชนิดของฟังก์ชันที่ถูกโอเวอร์โหลด) การอนุมานจะถูกทำจากลายเซ็นสุดท้าย (ซึ่งคาดว่าเป็นกรณี catch-all ที่อนุญาตมากที่สุด) เป็นไปไม่ได้ที่จะทำการแก้ไขโอเวอร์โหลดโดยอิงจากรายการชนิดของอาร์กิวเมนต์
พิจารณาตัวอย่างนี้:
function foo(a: number): number
function foo(a: string): string // last signature
function foo(a: number | string): number | string {
return null as any
}
type Fn = typeof foo
// returns last overloaded signature
type Arguments = Parameters<Fn> // [a: string]
Parameters จะคืนค่าลายเซ็นที่ถูกโอเวอร์โหลดล่าสุดของฟังก์ชันเสมอ
ลองเปลี่ยนลำดับดู:
function foo(a: string): string
function foo(a: number): number// last signature
function foo(a: number | string): number | string {
return null as any
}
type Fn = typeof foo
// returns last overloaded signature
type Arguments = Parameters<Fn> // [a: number]
ไม่มีวิธีใดที่จะส่งค่ากลับเป็นยูเนียนของพารามิเตอร์ทั้งหมดได้เพราะมันไม่ปลอดภัย ดูคำอธิบายทางการได้ที่นี่
มันไม่สามารถทำสิ่งนี้ในลักษณะที่ทั้งมีประโยชน์และถูกต้องได้จริง ๆ ลองพิจารณาฟังก์ชันแบบ
declare function fn(n1: number, n2: number): void; declare function doCall<T extends (a1: any, a2: any) => void>(func: T, a0: Parameters<T>[0], a1: Parameters<T>[1]): void; ```
ถ้า
Parameters<T>[0]ส่งกลับสตริง | ตัวเลขดังนั้น doCall(fn, 0, "")จะสําเร็จอย่างไม่ถูกต้อง ถ้าParameters<T>[0]>ส่งคืนสตริงและตัวเลขdoCall(fn, 0, 0)จะล้มเหลวอย่างไม่ถูกต้อง (และเป็นการเปลี่ยนแปลงครั้งใหญ่) โดยเฉพาะอย่างยิ่งด้วยประเภทเงื่อนไขและสหภาพแรงงานจริงๆแล้วฟังก์ชันประเภทเดียวที่ไม่สามารถพิมพ์ได้ด้วยการโอเวอร์โหลดเพียงครั้งเดียวคือฟังก์ชันที่มีโหมดความล้มเหลวนี้
พฤติกรรมปัจจุบันอย่างน้อยก็ทำให้การโทรบางอย่างได้รับการยอมรับอย่างถูกต้อง
คุณสามารถหาวิธีแก้ปัญหาบางอย่างได้ในกระทู้ GitHub ข้างต้น
