Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

193
Views
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 answers
Answer question

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!