Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

196
Vistas
Accessing Javascript class keys before class initialization

As I had a problem where my constructor became quite large and it started to become a problem maintaining it. I created this solution as a start of the refactor, however this still looked bulky. And it was easy to make a mistake.

    constructor(data: Partial<BusinessConfiguration>) {
    if(!data) return;
   
    this.logoId = data.logoId;
    this.positiveLogoId = data.positiveLogoId;
    this.negativeLogoId = data.negativeLogoId;
    this.faviconId = data.faviconId;
    this.primaryColor = data.primaryColor;
    this.windowTabName = data.windowTabName;
    this.shouldShowGDPR = data.shouldShowGDPR;
    this.allowsTermination = data.allowsTermination;
    this.styleConfiguration = data.styleConfiguration;
    this.shouldUseCustomTitle = data.shouldUseCustomTitle;
    this.processNotesStickers = data.processNotesStickers;
    this.terminationProcesses = data.terminationProcesses;
    this.shouldUseCustomHeader =data.shouldUseCustomHeader;
    this.completeDelete = data.completeDelete
    this.pingConfiguration = data.pingConfiguration;
    this.passwordConfiguration = data.passwordConfiguration;
    this.shouldAllowRandomRepeat = data.shouldAllowRandomRepeat;
    this.shouldRedirectImmediately = data.shouldRedirectImmediately;

}

So I created this, with this logic and good validation in my routes I never have to updated my constructor again. Whatever we send, those properties will be assigned. However, I am a bit unhappy with the fact that I am kind of brute forcing this. I want to check if the element from data, exists as a property of the class BusinessConfiguration.

    constructor(data: Partial<BusinessConfiguration>) {
    if(!data) return;
    
    Object.keys(data).forEach(element => {
        this[element] = data[element]
    });
   }

I had this problem on multiple occasions and maybe this is not the best example as I do have a type on data. But if data enters this constructor as type of any, mistakes and unwanted things may happen.

So bottom line is, How to access class property keys before object initialization.

I had an idea to create some kind of data structure which would hold all class property keys, but I hope there is something more clean. And if there is not, how would I go about making that as clean as possible, ideas are welcomed. Thank you in advance :)

about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

Rather than defining fields in the constructor, you can use public class fields:

class Business {
  // Defines a property but without a value (undefined).
  // You can add TypeScript types to these.
  logoId;
  positiveLogoId;
  negativeLogoId;
  // ...
}

Next, in the constructor you can include a loop that's similar to what you have, but with an extra filter:

class Business {
  logoId;
  positiveLogoId;
  negativeLogoId;

  constructor(data) {
    Object
      .keys(data)
      .filter(key => this.hasOwnProperty(key))
      .forEach((element) => {
        this[element] = data[element];
      });
  }
}

A different syntax, using the modern hasOwn and for...of:

class Business {
  logoId;
  positiveLogoId;
  negativeLogoId;

  constructor(data) {
    for (const [key, value] of Object.entries(data)) {
      if (Object.hasOwn(this, key)) {
        this[key] = value;
      }
    }
  }
}

Using either of the above, you can now only set properties that exist:

class Business {
  logoId;
  positiveLogoId;
  negativeLogoId;

  constructor(data) {
    for (const [key, value] of Object.entries(data)) {
      if (Object.hasOwn(this, key)) {
        this[key] = value;
      }
    }
  }
}

const b = new Business({
  logoId: 5,
  positiveLogoId: 10,
  foo: 1,
});

console.log(
  'Does the object contain "logoId"?', 
  Object.keys(b).includes('logoId'),
  '(should be true)'
);

console.log(
  'Does the object contain "foo"?', 
  Object.keys(b).includes('foo'),
  '(should be false)'
);

about 4 years ago · Juan Pablo Isaza Denunciar

0

The best answer I could come up with is to have a static variable on the class where I would store property names, but then this array needs to be updated, which is not much different than updating the constructor, but I do get an added benefit where I can access the keys of this class for this kind of operations if I need.

     class Business {
     private static keys = ['logoId', 'positiveLogoId', 'negativeLogoId']

     logoId;
     positiveLogoId;
     negativeLogoId;

     constructor(data: Partial<Business>) {
       Object.keys(data).forEach((element) => {
        if (Business.keys.includes(element))
           this[element] = data[element];
  });
}
}
      

    const obj = new Business({
    logoId: 5,
    positiveLogoId: '10',
    foo: 1
  }as any)

    console.log(obj) // Business { logoId: 5, positiveLogoId: '10'}
about 4 years ago · Juan Pablo Isaza Denunciar

0

You could introduce a helper that takes an object and an array of property names. Then returns a new object that only contains the given properties (if present).

function objSlice(obj, props = []) {
  return Object.fromEntries(
    props
      .filter(prop => prop in obj)
      .map(prop => [prop, obj[prop]])
  );
}

Example usage:

const data = { a: 1, b: 2, c: 3 };
objSlice(data, ["c", "a", "d"]);
//=> { c: 3, a: 1 }

You can use this in combination with Object.assign() and a static propNames attribute that holds allowed property names to very easily filter out undesired properties.

Object.assign(this, objSlice(data, this.constructor.propNames));

Here is an example:

class Book {
  static propNames = ["title", "author", "releaseYear"];

  constructor(data = {}) {
    Object.assign(this, objSlice(data, this.constructor.propNames));
  }
  
  toString() {
    return `${this.title} (${this.releaseYear}) - ${this.author}`;
  }
}

const helloWorld = new Book({
  title: "Hello World!",
  author: "John Doe",
  releaseYear: 1337,
  
  // undesired data property
  toString() {
    return "conflicting with Book method";
  },
});

console.log(`The book "${helloWorld}" was a good read.`);


// helper
function objSlice(obj, props = []) {
  return Object.fromEntries(
    props
      .filter(prop => prop in obj)
      .map(prop => [prop, obj[prop]])
  );
}

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda