ค้นหาเว็บไซต์

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 ทำงานกับประเภทตัวอักษรแบบสตริง:

บทความที่เกี่ยวข้อง