เห็น ไมโครซอฟ/TypeScript#41164 สำหรับ canonical องตอบคำถามคำถามข้อนี้
TypeScript ทำ อนุญาตแบบวงกลมจะอ้างอิงไปยังอยู่ ทั่วไป ส่วนเชื่อมต่อ และ ทั่วไป เรียนตั้งแต่ส่วนเชื่อมต่อและชั้นเรียนโหมี statically รู้จักทรัพย์สิน/สมาชิก/วิธีการ กุญแจเองและดังนั้นพ circularity เกิดขึ้นใน"ปลอดภัย"สถานที่ชอบทรัพย์สิน มีค่าs หรือวิธีการพารามิเตอร์หรือกลับมาแบบนั้น
interface Interface<T> { val: T }
type X = Interface<X> // okay
class Class<T> { method(arg: T): void { } }
type Y = Class<Y> // okay
แต่สำหรับทั่วไป พิมพ์นามแฝง ไม่มีวันรับรองว่า. พิมพ์นามแฝงสามารถมีโครงสร้างนั่นไหนไม่ระบุชื่อประเภทจะต้องดังนั้นศักยภาพเพียงพอที่ circularity ไม่ constrained จะ recursive ต้นไม้-เหมือนวัตถุ:
type Safe<T> = { val: T };
type Unsafe<T> = T | { val: string };
ตอนที่คอมไพเลอร์ instantiates เป็นประเภททั่วไปมั defers ของมันประเมินผลมันยังไม่ทันทีเลยพยายามเต็มที่คำนวณผลลัพธ์จากประเภทนี้ได้นะ ทั้งหมดที่มันมองเห็นเป็นรูปแบบ:
type WouldBeSafe = Safe<WouldBeSafe>;
type WouldBeUnsafe = Unsafe<WouldBeUnsafe>;
ทั้งสองของพวกนั้นดูเหมือนกัไปที่คอมไพเลอร์... type X = SomeGenericTypeAlias<X>
. มันไม่สามารถ"เห็น"นั่น WouldBeSafe
ไม่เป็นไรหรอ:
//type WouldBeSafe = { val: WouldBeSafe }; // would be okay
ในขณะที่ WouldBeUnsafe
อาจจะเป็นปัญหา:
//type WouldBeUnsafe = WouldBeUnsafe | { val: string }; // would be error
ตั้งแต่มันไม่สามารถเห็นความแตกต่าง,และเพราะอย่างน้อยก็บางอย่า usages นจะเป็นอย่างผิดกฏหมายแบบวงกลมมันแค่ prohibits พวกเขาทั้งหมด
ดังนั้น,คุณสามารถทำอะไรได้บ้าง? นี่คือหนึ่งในพวกนั้นคดีที่ฉันจะขอแนะนำให้ใช้ interface
แทนที่จะเป็น type
ตอนที่คุณทำได้ คุณสามารถเขียนใหม่ของคุณ record
ชนิด(การเปลี่ยนมัน MyRecord
สำหรับการตั้งชื่อประชุมด้วยเหตุผล)เป็นข้ interface
และทุกอย่างที่จะทำงาน:
interface MyRecord<T> { val: T };
type B = MyRecord<B>; // okay
คุณสามารถแม้แต่จะเขียนใหม่ของคุณ func
ชนิด(การเปลี่ยนมัน Func
สำหรับการตั้งชื่อประชุมด้วยเหตุผลอีกครั้ง)เป็นข้ interface
โดยการเปลี่ยน ฟังก์ชันประเภทรแสดง ไวยากรณ์เข้าไปใน โทรลายเซ็นต์รูปแบบการสั่งงาน:
interface Func<T> { (arg: T): void }
type C = Func<C>; // okay
แน่นอนมีสถานการณ์ที่คุณไม่สามารถทำอย่างนั้นโดยตรงอย่างเช่นที่สร้าง Record
เครื่องมือประเภท:
type Darn = Record<string, Darn>; // error
และคุณไม่สามารถเขียนใหม่ใน แผนไว้ประเภท Record
เป็นข้ interface
. และแน่นอนมันคงจะไม่ปลอดภัยที่จะพยายามที่จะทำให้กุญแจแบบวงกลมเหมือน type NoGood = Record<NoGood, string>
. ถ้าเพียงแต่คุณต้องการจะทำ Record<string, T>
สำหรับทั่วไป T
คุณ สามารถ เขียนใหม่ มัน เป็น interface
:
interface Dictionary<T> extends Record<string, T> { };
type Works = Dictionary<Works>;
ดังนั้นมันค่อนข้างบ่อยนักหนทางที่จะใช้เป็น interface
แทนที่จะเป็น type
เพื่ออนุญาตให้คุณต้องแสดงถึงความสน"ปลอดภัย"recursive ยชนิด
สนามเด็กเล่นเชื่อมโยงไปยังนรหัส