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

วิธีการทำให้ enum ของสตริงใน Typescript มีค่า key และ value เหมือนกัน


ฉันต้องการสร้างประเภททั่วไปที่ตรวจสอบสิ่งต่อไปนี้ใน enum:

  1. ทุกฟิลด์เป็นสตริง
  2. ค่าทั้งหมดเท่ากับกุญแจของตัวเอง

ดังนั้นในกรณีใด ตัวแปร enum ต่อไปนี้จะถือว่าถูกต้อง:

enum correct1 {
  bar = 'bar',
  baz = 'baz',
}

enum correct2 {
  quux = 'quux',
}

แต่สิ่งต่อไปนี้จะไม่:

enum wrongFoo {
  bar = 'bar',
  baz = 'WRONG',
}

enum wrongFoo2 {
  bar = 1
}

ไวยากรณ์ที่ถูกต้องในการทำให้สิ่งนี้เกิดขึ้นคืออะไร?

คำตอบ #1

หากคุณโอเคกับการตรวจสอบเวลาคอมไพล์แบบแมนนวล (ซึ่งหมายความว่าคุณต้องเขียนบางอย่างด้วยตนเองหลังจากการกำหนด enum) คุณสามารถทำสิ่งนี้ได้:

type EnsureCorrectEnum<T extends { [K in Exclude<keyof T, number>]: K }> = true;

จากนั้นให้ตัวคอมไพเลอร์ประเมิน EnsureCorrectEnum<typeof YourEnumObjectHere> หากสามารถคอมไพล์ได้ ดีมาก หากไม่สามารถคอมไพล์ได้ แสดงว่ามีปัญหา:

type Correct1Okay = EnsureCorrectEnum<typeof correct1>; // okay
type Correct2Okay = EnsureCorrectEnum<typeof correct2>; // okay

type WrongFooBad = EnsureCorrectEnum<typeof wrongFoo>; // error!
//   ┌─────────────────────────────> ~~~~~~~~~~~~~~~
// Types of property 'baz' are incompatible.

type WrongFoo2Bad = EnsureCorrectEnum<typeof wrongFoo2>; // error!
//   ┌──────────────────────────────> ~~~~~~~~~~~~~~~~
// Types of property 'bar' are incompatible.

ข้อผิดพลาดก็อธิบายได้ค่อนข้างชัดเจนเช่นกัน

โอเค หวังว่านี่จะช่วยได้ โชคดีนะ!

ลิงก์ไปยังโค้ด

คำตอบ #2

วิธีทางเลือกที่หลีกเลี่ยงการต้องประกาศชนิดใหม่สำหรับการตรวจสอบแต่ละครั้ง:

const keyValuesMatch = <T>(kv: { [K in keyof T]: K }) => {};

enum correct {
  bar = 'bar',
  baz = 'baz',
}
enum incorrect {
  bar = 'bar',
  baz = 'wrong',
}

keyValuesMatch(correct);
keyValuesMatch(incorrect); // Type 'incorrect.baz' is not assignable to type '"baz"'.

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