typescript - ความแตกต่างระหว่าง string enums และ string literal types ใน TS
สมมติว่าฉันต้องการให้แน่ใจว่า myKey ใน { myKey: '' } มีเพียงสตริง foo, bar, baz เท่านั้น ฉันสามารถทำได้สองวิธี
// with a String Literal Type
type MyKeyType = 'foo' | 'bar' | 'baz';
// or with a String Enum
enum MyKeyType {
FOO = 'foo',
BAR = 'bar',
BAZ = 'baz'
}
ฉันสงสัยว่าข้อดีและข้อเสียของสิ่งหนึ่งเมื่อเทียบกับอีกสิ่งหนึ่งคืออะไร เพราะทั้งสองดูเหมือนกันสำหรับฉัน (ยกเว้นวิธีที่ฉันจะเข้าถึงค่าต่าง ๆ เช่น สำหรับการตรวจสอบเงื่อนไข)
ความแตกต่างเพียงอย่างเดียวที่ฉันพบในเอกสาร TS คือ Enum เป็นวัตถุจริงในขณะรันไทม์ ซึ่งอาจเป็นที่ต้องการในบางกรณี
คำตอบ #1
ก็มี ความแตกต่าง ระหว่าง string enums และ literal types ในโค้ดที่ถูก transpile
เปรียบเทียบโค้ด Typescript
// with a String Literal Type
type MyKeyType1 = 'foo' | 'bar' | 'baz';
// or with a String Enum
enum MyKeyType2 {
FOO = 'foo',
BAR = 'bar',
BAZ = 'baz'
}
ด้วย โค้ด JavaScript ที่ถูกแปลงแล้ว
// or with a String Enum
var MyKeyType2;
(function (MyKeyType2) {
MyKeyType2["FOO"] = "foo";
MyKeyType2["BAR"] = "bar";
MyKeyType2["BAZ"] = "baz";
})(MyKeyType2 || (MyKeyType2 = {}));
สิ่งที่คุณเห็นคือ ไม่มีโค้ดที่ถูกสร้างขึ้นสำหรับสตริงลิเทอรัล เพราะ Transpiler ของ TypeScript ใช้เพียงเพื่อความปลอดภัยของชนิดข้อมูลในขณะ transpiling ในขณะ runtime สตริงลิเทอรัลจะถูก "สร้างเป็นสตริงธรรมดา" ไม่มีการเชื่อมโยงระหว่างการกำหนดลิเทอรัลกับการใช้งาน
ดังนั้นจึงมีทางเลือกที่สามเรียกว่า const enum
ดูอันนี้
// with a String Literal Type
type MyKeyType1 = 'foo' | 'bar' | 'baz';
// or with a String Enum
enum MyKeyType2 {
FOO = 'foo',
BAR = 'bar',
BAZ = 'baz'
}
// or with a Const String Enum
const enum MyKeyType3 {
FOO = 'foo',
BAR = 'bar',
BAZ = 'baz'
}
var a : MyKeyType1 = "bar"
var b: MyKeyType2 = MyKeyType2.BAR
var c: MyKeyType3 = MyKeyType3.BAR
จะถูกแปลงโค้ดเป็น
// or with a String Enum
var MyKeyType2;
(function (MyKeyType2) {
MyKeyType2["FOO"] = "foo";
MyKeyType2["BAR"] = "bar";
MyKeyType2["BAZ"] = "baz";
})(MyKeyType2 || (MyKeyType2 = {}));
var a = "bar";
var b = MyKeyType2.BAR;
var c = "bar" /* BAR */;
สำหรับการเล่นเพิ่มเติมคุณสามารถตรวจสอบลิงค์นี้
ฉันชอบกรณี const enum เพราะสะดวกในการพิมพ์ Enum.Value Typescript จะดูแลส่วนที่เหลือให้ฉันเพื่อให้ได้ประสิทธิภาพสูงสุดเมื่อทำการแปลงโค้ด
คำตอบ #2
สิ่งสำคัญที่ต้องเข้าใจคือ ค่าของ enum แบบสตริงเป็นสิ่งที่ไม่เปิดเผย
กรณีการใช้งานที่ตั้งใจสำหรับ string enum คือคุณไม่ต้องการให้โค้ดอื่นรู้หรือสนใจว่าสตริง literal ที่รองรับ MyKeyType.FOO คืออะไร ซึ่งหมายความว่าคุณจะไม่สามารถส่ง สตริง literal "bar" ไปยังฟังก์ชันที่รับ MyKeyType ได้โดยตรง — คุณจะต้องเขียน MyKeyType.BAR แทน
คำตอบ #3
หนึ่งในประโยชน์ของการใช้ enum ในช่วงเวลาการพัฒนาคือคุณจะเห็นรายการตัวเลือกได้อย่างง่ายดายผ่าน intellisense:
เช่นเดียวกัน คุณสามารถเปลี่ยนค่าของ enum ได้อย่างง่ายดายโดยใช้เครื่องมือปรับปรุงโค้ด แทนที่จะต้องเปลี่ยนสตริงทุกที่
แก้ไข: ใน VS 2017 และ TypeScript >=3.2.4, Intellisense ทำงานกับประเภทตัวอักษรแบบสตริง:

