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

ทำไมชนิดของอาร์กิวเมนต์ของฟังก์ชัน ซึ่งเป็นสมาชิกของวัตถุ (typescript) จึงไม่ได้รับการกำหนด?


มีใครช่วยฉันได้ไหม? นี่คือตัวอย่าง 3 ตัว: a, b, c สำหรับตัวแรกและตัวที่สอง ประเภทของ "arg" คือ true (ตัวเลข) สำหรับตัวที่สาม typescript ไม่สามารถระบุประเภทของ "arg" ได้

function a<T extends (value: number) => string>(
    arg: T,
) {
    return null;
}

a((arg) => arg.toExponential()); // ARG HAS RIGHT TYPE: number

function b<T extends { [index: string]: (value: number) => string }>(
    arg: T,
) {
    return null;
}
b({ x: (arg) => arg.toExponential() }); // ARG HAS RIGHT TYPE: number

function c<K extends { [index: string]: number }, T extends {[P in keyof K]?: ((value: number) => string) }>(
    arg1: K,
    arg2: T,
) {
    return null;
}
c({ x: 15 }, { x: (arg) => arg.toExponential() }); // ARGS NOT HAS TYPE: any

คำตอบ #1

คอมไพเลอร์จะสับสนเล็กน้อยเมื่อพารามิเตอร์ประเภทสองตัวมีความขึ้นต่อกันและตัวหนึ่งต้องคาดเดาโดยขึ้นอยู่กับอีกตัวหนึ่ง วิธีแก้ปัญหาแบบง่ายที่ฉันใช้คือการเรียกสองขั้นตอน ฟังก์ชันแรกกำหนดประเภทของอาร์กิวเมนต์ตัวแรก และการเรียกครั้งที่สองสามารถให้ประเภทที่เหลือถูกคาดเดาได้:

function c<K extends { [index: string]: number }>(arg1: K)
{
    return function <T extends {[P in keyof K]?: ((value: number) => string) }>(arg2: T){
    };
}


c({ x: 15 })({ x: (arg) => arg.toExponential() }); // arg will be number

แก้ไข

แม้วิธีแก้ปัญหาดังกล่าวข้างต้นจะใช้งานได้และสรุปค่า T ได้ถูกต้อง ตามที่ @MihailMalostanidis แนะนำ แต่ในกรณีนี้อาจไม่จำเป็นต้องใช้พารามิเตอร์ตัวที่สองเลย ซึ่งวิธีนี้ก็สามารถสรุปค่าได้ถูกต้องเช่นกัน:

function c<K extends { [index: string]: number } >(
    arg1: K,
    arg2: {[P in keyof K]?: ((value: number) => string) },
)  {
    return null;
}

ความแตกต่างคือหากคุณส่งค่ากลับ arg2 จากฟังก์ชัน (หรือประเภทที่อิงจาก T) ในเวอร์ชันนี้คีย์ทั้งหมดของ K จะปรากฏ ไม่ใช่แค่คีย์ที่ระบุจริง ๆ ใน arg2 เมื่อเรียกใช้ ขึ้นอยู่กับกรณีการใช้งานของคุณ สิ่งนี้อาจยอมรับได้ แต่โซลูชันเริ่มต้นสามารถใช้ได้ในทุกกรณี