ทำไมชนิดของอาร์กิวเมนต์ของฟังก์ชัน ซึ่งเป็นสมาชิกของวัตถุ (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 เมื่อเรียกใช้ ขึ้นอยู่กับกรณีการใช้งานของคุณ สิ่งนี้อาจยอมรับได้ แต่โซลูชันเริ่มต้นสามารถใช้ได้ในทุกกรณี
