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

lambda - TypeScript, วิธีส่งชื่อฟิลด์สาธารณะด้วยนิพจน์ที่มีประเภท


ฉันกำลังพยายามหาวิธีส่งอาร์เรย์ของชื่อคุณสมบัติ (หรือชื่อฟิลด์) ของอ็อบเจ็กต์ที่กำหนด โดยไม่ใช้สตริงเวทย์มนตร์ที่เรียกว่า - เพราะง่ายต่อการพิมพ์ผิด! โดยพื้นฐานแล้ว ฉันกำลังมองหาบางสิ่งที่เกี่ยวข้องกับ "Expression<>" ของ C# ฉันคิดว่า

ตัวอย่างเช่น กับสตริงวิเศษ: searchFilter(model, 'searchParameter', ['id', 'name'])

เช่น พิมพ์ หรือวิธีที่ฉันต้องการเรียกฟังก์ชัน: searchFilter(model, 'searchParameter', [m => m.id, m => m.name])

เพื่อเป็นการอ้างอิง ฟังก์ชันนี้มีลักษณะประมาณนี้:

ด้วยสตริงเวทย์มนตร์: (หรือว่าฉันพยายามทำมันแบบมีการพิมพ์ประเภท)

private searchFilter(mode: Model, q: string, properties: string[]): boolean {
   if (q === '') return true;

   q = q.trim().toLowerCase();

   for (let property of properties) {
     if (vacature[property.toString()].toString().toLowerCase().indexOf(q) >= 0) {
       return true;
     }
  }

  return false;
}

typed: (หรือว่าฉันพยายามทำมันแบบ typed แต่แน่นอนว่านี่แค่คืนฟังก์ชันกลับมา.. ฉันจำเป็นต้องมี 'function expression' ที่เกี่ยวข้องตามใน C# เพื่อดึง property ที่ถูกเรียกใช้ เพื่อที่จะได้ชื่อของมัน)

private searchFilter(mode: Model, q: string, propertySelector: ((x: Model) => any | string)[]): boolean {
   if (q === '') return true;

   q = q.trim().toLowerCase();

   for (let property of propertySelector) {
     if (vacature[property.toString()].toString().toLowerCase().indexOf(q) >= 0) {
       return true;
     }
  }

  return false;
 }

คำตอบ #1

คุณไม่สามารถกำจัดสตริงนั้นได้ ไม่มีสิ่งที่เรียกว่า nameof property ใน TypeScript (ตอนนี้ยังไม่มี)

อย่างไรก็ตาม สิ่งที่คุณสามารถทำได้คือพิมพ์บางสิ่งเป็นคีย์ของชนิดอื่น

แบบนี้

interface Model {
    a: string,
    b: number
}

function searchFilter(model: Model, q: keyof Model) { }

ผลลัพธ์ที่ได้คือ:

searchFilter(null, 'a') // works
searchFilter(null, 'b') // works
searchFilter(null, 'c') // error c is not a property of Model

คุณสามารถพิมพ์อาร์เรย์ของคุณสมบัติของชนิดข้อมูลได้เช่นนี้:

function searchArray(model: Model, q: string, properties: Array<keyof Model>) { }

searchArray(null, 'blabla', ['a', 'b'])

คำตอบ #2

Nameof ไม่มีให้ใช้งานโดยตรง แต่ฟังก์ชันนี้ถูกจำลองขึ้นมาด้วยไลบรารีของบุคคลที่สาม

คุณสามารถทำให้ได้ฟังก์ชัน nameof โดยใช้ไลบรารีของบุคคลที่สาม (https://www.npmjs.com/package/ts-nameof). คุณสามารถดูซอร์สโค้ดได้ที่นี่: https://github.com/dsherret/ts-nameof

ในกรณีนี้ ไลบรารีได้จัดเตรียมตัวเลือกหลายแบบขึ้นอยู่กับระดับของชื่อวัตถุที่คุณต้องการใช้ เช่น ชื่อของตัวแปรเอง ชื่อของเมธอด ชื่อของเมธอดพร้อมกับคลาสที่บรรจุอยู่ และอื่น ๆ (ตอนย่อจากเอกสารของไลบรารี)

ด้านล่างแสดงผลลัพธ์ของ JavaScript ที่ถูกแปลงทางซ้าย และรูปแบบเทียบเท่าของ TypeScript ทางด้านขวา

console.log("console");             // console.log(nameof(console));
console.log("log");                 // console.log(nameof(console.log));
console.log("console.log");         // console.log(nameof.full(console.log));
console.log("alert.length");        // console.log(nameof.full(window.alert.length, 1));
console.log("length");              // console.log(nameof.full(window.alert.length, 2));
console.log("length");              // console.log(nameof.full(window.alert.length, -1));
console.log("alert.length");        // console.log(nameof.full(window.alert.length, -2));
console.log("window.alert.length"); // console.log(nameof.full(window.alert.length, -3));

"MyInterface";                      // nameof<MyInterface>();
console.log("Array");               // console.log(nameof<Array<MyInterface>>());
"MyInnerInterface";                 // nameof<MyNamespace.MyInnerInterface>();
"MyNamespace.MyInnerInterface";     // nameof.full<MyNamespace.MyInnerInterface>();
"MyInnerInterface";                 // nameof.full<MyNamespace.MyInnerInterface>(1);
"Array";                            // nameof.full<Array<MyInterface>>();
"prop";                             // nameof<MyInterface>(o => o.prop);

สตริงเหล่านี้จะถูกแทนที่ในเวลาการแปลงโค้ด ดังนั้นจึงไม่ควรมีผลต่อประสิทธิภาพในระหว่างการรันไทม์