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

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 ข้างต้น

บทความที่เกี่ยวข้อง