node.js - Bagaimana saya bisa mengekspos semua properti dalam suatu entitas menggunakan dekorator @Expose dari class-transformer?


Saya menggunakan pustaka class-transformer dalam proyek saya yang diimplementasikan di NodeJS, tetapi saya tidak menemukan cara untuk menampilkan semua properti dari entitas saya. Saya mencoba menggunakan dekorator @Expose() di tingkat kelas, tetapi itu tidak berhasil. Saya berharap menemukan solusi karena agak melelahkan menggunakan dekorator expose pada setiap properti di kelas.

Contoh dari apa yang sedang saya coba capai:

  @Expose() // Expose all properties
  export class User {
     name: string;
     phone: string;
     age: number
  };

Saat ini itu hanya berfungsi jika saya mendefinisikan expose pada setiap properti:

  export class User {
    @Expose() name: string;
    @Expose() phone: string;
    @Expose() age: number
  };

Jawaban #1

Masalah

Satu-satunya masalah yang saya lihat adalah, sebuah dekorator ketika diterapkan pada deklarasi kelas tidak memungkinkan Anda untuk mengakses propertinya secara langsung. Alasan dari perilaku seperti itu adalah karena objek belum ada di memori, sampai titik ini, objek tersebut belum diinstansiasi, dan masih hanya prototipe. Berikut hal yang sama yang ditunjukkan dengan contoh sederhana:

const Demo = (target: any, propertyKey: string) => {
  console.log({
    target, // [class Human]
    propertyKey, // undefined
  });

  console.log({
    props: Object.keys(target), // [] (Makes sense as it is not an instance, just a class declaration.)
  });
};

@Demo
class Human {
  name: string;
}

Sekarang, solusinya jelas untuk masalah di atas, kita bisa membuat sebuah instance dari target dan kemudian mengambil prototipenya. Inilah titik tepat yang membantu saya menyelesaikan masalah ini.

Langkah-langkah untuk menyelesaikan kasus penggunaan ini:

  1. Buat dekorator kustom
  2. Batasi dekorator pada deklarasi kelas.
  3. Buat instance dari deklarasi kelas kami dan ambil properti kelas.
  4. Terapkan class-transformers @Expose ke target ini untuk setiap kunci yang diambil pada langkah 3
  5. Gunakan dekorator kustom kami
  6. Saatnya untuk lebih banyak contoh sekarang.

Solusi

import "reflect-metadata";
import { Expose } from "class-transformer";

// 1. Create a custom decorator
const ClassExpose = () => (target: any, _propertyKey: string) => {
  // 1.1 Allow decorator only on class
  if (!target) {
    throw new Error(
      "@Expose is not used on class. It must be on class. Example @Export()\nclass Sample{}"
    );
  }

  // 1.2 Create instance of target and fetch its keys
  const instance = new target();
  const props = Object.keys(instance);

  // 1.3 Apply class-transformer expose function to each key
  props.forEach((key) => Expose()(target, key));
};

// 2. Use our custom Decorator
@ClassExpose() // Expose all properties
export class User {
  name: string;
  phone: string;
  age: number;
}

Contoh 1: (Dengan Konstruktor)

Penggunaan dekorator kustom kami pada kelas dengan konstruktor kustom

@ClassExpose()
export class UserAccountWithConstructor {
  constructor(name: string) {
    this.name = name;
  }
  name: string;
  phone: string;
  age: string;
}

Contoh 2: (Dengan Fungsi)

Penggunaan dekorator kustom kami pada kelas dengan fungsi-fungsi di kelas

@ClassExpose()
export class UserAccount {
  constructor(name: string) {
    this.name = name;
  }
  name: string;
  phone: string;
  age: string;

  protected checkCredentials() {
    console.log("checking credentials...");
  }

  private isPhoneValid() {
    console.log("is phone valid...");
  }

  private login() {
    console.log("logging in...");
  }
}

Artikel terkait