Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

194
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda