typescript - วิธีประกาศชนิดของฟังก์ชัน const `f=({ a=0 }={}) => a` ใน TS
ฉันใช้การระบุประเภทใน TS เป็นเหมือนเอกสารประกอบ สำหรับฉัน มันเป็นเรื่องดีที่จะรู้ว่าฟังก์ชันของฉันจะจัดการประเภทใดบ้างตั้งแต่ต้น
ฉันยังหาแนวทางในการประกาศชนิดของฟังก์ชันประเภทนี้ไม่ได้ คอมไพเลอร์จะสรุปชนิดเอง แต่เมื่อฉันพยายามกำหนดหมายเหตุด้วยชนิดเดียวกันเอง มันก็ล่ม
ยกตัวอย่างฟังก์ชันนี้:
// compiler infers the type
// f: ({ a }?: { a?: number | undefined }) => number
const f = ({ a = 0 } = {}) => a;
แต่เมื่อฉันพยายามทำหมายเหตุ มันล้มเหลวพร้อมข้อผิดพลาดดังต่อไปนี้
const f: ({ a }?: { a?: number | undefined }) => number =
({ a = 0 } = {}) => a;
// ^
// \-- Property 'a' does not exist on type '{ a?: number | undefined; } | undefined'
คำตอบ #1
มันดูเหมือนเป็นบั๊กในคอมไพเลอร์ หรืออย่างน้อยก็เป็นข้อจำกัดที่น่าเสียดาย ผมยังไม่พบปัญหาที่มีอยู่ใน GitHub เกี่ยวกับสถานการณ์เฉพาะนี้ microsoft/TypeScript#35160 ดูเหมือนจะเกี่ยวข้อง แต่ก็ไม่ได้ตอบว่าเหตุการณ์แบบนี้เกิดขึ้นได้อย่างไร ผมได้ยื่น microsoft/TypeScript#37271 เพื่อหาข้อมูลว่ากำลังเกิดอะไรขึ้น; ผมจะแจ้งที่นี่ถ้าผมได้รับข้อมูลเพิ่มเติม
อัปเดต: นี่คือบั๊กของคอมไพเลอร์ที่ถูกแก้ไขใน typescript@next และจะถูกปล่อยใน TypeScript 3.9.1 เมื่อถูกปล่อยแล้ว คำตอบที่นี่ก็จะเป็นแค่ "อัปเดตเวอร์ชัน TS ของคุณ" สำหรับเวอร์ชันก่อนหน้าและสำหรับผู้สนใจอื่น ๆ ส่วนที่เหลือของคำตอบยังคงเหมือนเดิม
แต่คำถามของคุณคือวิธีการใส่คำอธิบายประกอบ ดังนั้นก่อนอื่นมาดูกันว่าคอมไพเลอร์ไม่ได้บ้าไปทั้งหมดและประเภทที่แสดงเมื่อคุณวางเมาส์เหนือ f นั้นเข้ากันได้กับมันจริง ๆ:
const f = ({ a = 0 } = {}) => a;
const g: ({ a }?: { a?: number; }) => number = f; // no error
นั่นใช้ได้ ดังนั้นปัญหาต้องอยู่ที่เมื่อคุณระบุชนิดของ f อย่างชัดเจน มันจะให้ชนิดตามบริบทสำหรับพารามิเตอร์ ซึ่งคอมไพเลอร์ไม่พอใจด้วยเหตุผลบางอย่าง (ซึ่งอาจจะเป็นบั๊ก) วิธีแก้ปัญหาที่ผมนึกได้คือระบุชนิดของพารามิเตอร์นี้อย่างชัดเจน:
const h: ({ a }?: { a?: number }) => number =
({ a = 0 }: { a?: number } = {}) => a; // no error
นั่นก็ใช้ได้ มันแปลกที่คุณต้องระบุชนิดทั้งฟังก์ชันลูกศรและพารามิเตอร์ของมัน แต่ก็ยังดีที่คุณมีแนวทางไปข้างหน้า หวังว่าจะช่วยได้ โชคดี!
ลิงก์ Playground ไปยังโค้ด
คำตอบ #2
ถ้าฉันเข้าใจสิ่งที่คุณพูดถูกต้อง คุณควรสามารถแทนที่ { a } ด้วยชื่อผันแปรที่คุณเลือกได้:
const f: (v?: {a?: number | undefined}) => number = ({ a = 0 } = {}) => a;
เพราะคุณกำลังอธิบายรูปร่างของอาร์กิวเมนต์ในคำอธิบายประกอบ คุณไม่จำเป็นต้องระบุว่า a เป็นสมาชิกในประกาศพารามิเตอร์
