เมื่อคุณต้องกา TypeScript คอมไพเลอร์(tsc
)เพื่อ transpile TypeScript รหัสเข้า runnable จาวาสคริปต์,ภาษาเป็นรูปแบบชนิดของระบบเป็ นลบ. ดังนั้นของคุณ Foo
ประเภท(renamed ให้เป็นอักษรตัวพิมพ์ใหญ่จะมาพบ TS ตั้งชื่อ conventions)ไม่ใช่ของขวัญในรูปแบบที่ runtime. ไม่มีอะไรที่คุณสามารถ iterate ไปเอากุญแจ go
แล้ว start
.
คนส่วนใหญ่ตรงไปตรงมาทางที่จะเอาอะไรบางอย่างที่จะเกิดขึ้นตอน runtime คือต้องเขียนจาวาสคริปต์จำเป็นต้องทำมันและจากนั้นก็ต้องทำให้แน่ใจว่า TypeScript คอมไพเลอร์สามารถให้คุณแข็งแกร่งประเภทคุณต้องการขณะที่คุณกำลังเขียนมัน นี่มัน ย้อนกลับ ของสิ่งที่คุณกำลังพยายามทำอยู่
ในกรณีของคุองอะไร generate()
ต้องการเพื่อทำงานที่ runtime? ถ้าเราสามารถสรุปได้ว่าค่าที่ถูกสร้างโดย generate()
จะเป็นสิ่งเดียวที่ถืออยู่ string
-ลที่มีคุณค่าของคุณสมบัติงั้นเราต้องผ่านมันเป็นรายชื่อของกุญแจของวัตถุ. ดังนั้นถ้าเราเขียน generate()
ต้องทำอย่างนั้นแล้วก็กำหนด Foo
ในแง่ของการส่งออกของ generate()
แทนที่จะมีทางจะเป็นอย่างอื่นไป?
สำหรับตัวอย่าง:
function generate<K extends PropertyKey>(...keys: K[]) {
return Object.fromEntries(keys.map(k => [k, ""])) as { [P in K]: string };
}
const myFooObject = generate("go", "start");
type Foo = typeof myFooObject;
/* type Foo = {
go: string;
start: string;
} */
console.log(myFooObject)
/* {
"go": "",
"start": ""
} */
อยู่ที่นี่ generate()
คือ ทั่วไป ฟังก์ชันที่ต้องใช้รายชื่อของกุญแจ(ประเภท K
และได้เป็นค่าของประเภทกับกุญแจอยู่ K
แล้วค่าประเภท string
. นั่น {[P in K]: string}
เป็น แผนไว้ประเภท มพล่ามคำเชยๆออกมาไม่หยุดไป Record<K, string>
โดยใช้ คน Record<K, V>
เครื่องมือชนิด.
ที่ implementation ใช้ Object.fromEntries()
เพื่อสร้างของและกลับประเภทคือ asserted ต้องเป็นที่ถูกต้องประเภทเพราะ TypeScript นมองเห็น Object.fromEntries()
ที่กลับมาเป็นประเภทนั่นเป็นเหมือนกัว้างสำหรับวัตถุประสงค์ของเรา
ยังไงตอนที่คุณโทรหา const myFooObject = generate("go", "start")
มันยานี้ขึ้นมาเป็นค่าประเภท {go: string; start: string}
ซึ่งเป็นเหมือนกับของคุณ Foo
ประเภทนี้ได้นะ ดังนั้นเราสามารถกำหนด Foo
เป็ type Foo = typeof myFooObject
แทนที่จะทำมันด้วยตัวคุณเอง คุณ อาจจะ ยังคงทำมันด้วยตนเองแต่ประเด็นฉันมาที่นี่ก็คือมันง่ายมากเลยที่จะเขีย แห้งหัส ใน TypeScript ถ้าคุณเริ่มด้วยค่าและสร้างประเภทจากพวกเขาแทนที่จะพยายามทำมันตรงกันข้ามกันเลยนะ
อีกครั้งถ้าคุณใช้ TypeScript คอมไพเลอร์ tsc
ที่นี่,งั้นประเภท erasure จะปกป้องคุณจากการเขียน generate()
จากนิยามของ Foo
. แต่..
ถ้าคุณพร้อมที่จะเพิ่มเป็นสร้างก้าวของโครงการและแสดง รหัสคนรุ่น ใช้ TypeScript คอมไพเลอร์รูปแบบ api หรือบางอย่างเหมือนมันคุณสามารถงั้นก็ทำไปเรื่อยเปื่องอย่างกับชนิด มันมีบรรณารักษ์นั่นทำอย่างที่คล้ายกันอย่างที่ต้องสิ่งที่คุณต้องกา;สำหรับตัวอย่างเช่น ts-โดยอัตโนมัติล้อเลียน อ้างว่าจะสร้างล้อเลียวัตถุนให้เป็นวัตถุชนิดซึ่งดูเหมือนสิ่งของคุณใช้กรณีนี้
ช่างเป็นพิเศษสร้างขั้นอาจจะเป็นสมเหตุสมผลวิธีของคุณดีแต่ถ้าคุณลงไปตรงนั้นเส้นทางที่คุณควรจำไว้ว่าคุณไม่ได้ใช้ความ TypeScript อีกแล้ว(และเพราะฉะนั้นเรื่ออาจจะออกจากขอบเขตสำหรับคำถามกับแค่ TypeScript ป้ายกำกับ).
สนามเด็กเล่นเชื่อมโยงไปยังนรหัส