skip to Main Content

Looks like it is not really feasible or very tricky still I’ll take a try.

Say we have a config data of a fluent structure for user to provide.

E.g.

configRoot:
  fluentSubSection:
     someProp: 12
     valueOf: John Doe
     toString: whatever
     toJSON:
        implementation: 'some-npm-one'
        indentation: 2

How to make

  • The user possible to provide really any data without any restrictions on property names
  • Same time to be able to customize the functionality of ConfigNode representation class with some standard handlers such as toString, valueOf, toJSON

Whether it possible it achieve the same functionality on some Symbol/Proxy/Other-Hucky way. So that To split the functional and data level representation. Still to leave the natural data access through the pure properties way (without any accessors e.g. node.readProperty(‘propertyName’)

E.g.

const config = loadConfig('...')
console.log(config.configRoot.fluentSubSection.valueOf) 
// John Doe
// plain content data access outputs the value provided by user

console.log(config.configRoot.fluentSubSection.toString) 
// whatever 
// plain content data access outputs the value provided by user

Still the ConfigNode instance it self should have some custom functionality under the hood (without harm for plain acccess to a user provided data properties) as

// Customize in some hucky way the functionality
ConfigNode[#toString_Symbol] = () => `[Custom ConfigNode - ${
  Object.entries(this)
    .map(
      [key,  value] => `${key}: ${value}`
    ).join(';')
}]`
ConfigNode[#toJSON_Symbol] = () => JSON.stringify(
    {...this}, 
    null, 
    this.toJSON?.indentation // the value from a data access level
)

console.log(String(config.configRoot.fluentSubSection)) 
// Should switch to some functional level access for toString implementation 
// E.g. [Custom ConfigNode - someProp: 12; valueOf: John Doe; toString: whatever]

JSON.parse(config.configRoot.fluentSubSection)
// Should switch to custom JSON marshaling implementation

So how to customize toJSON, toString, valueOf, etc. related functionality of ConfigNode class and still to be able to provide same data properties as a plain regular values.

P.S. maybe someone grasp the idea and can see how to express the issue in more clear way please help as well 🙂

Anyway please any ideas are appreciated.
Thx

2

Answers


  1. Chosen as BEST ANSWER

    Actually for now I've found a partial solution with Symbol.toPrimitive which solves the issue for toString and valueOf.

    Actually it allows achieve the same just on step earlier and without populating the data properties scope with method functions.

    class ConfigNode {
    [props: string]: any;
    
    [Symbol.toPrimitive]() {
        return `[Custom ConfigNode Representation]`
    }
    
    }
    
    const node = new ConfigNode()
    node.toString = 'whaterver'
    
    console.log(`${node}`) // [Custom ConfigNode Representation]
    console.log(node.toString) // whaterver
    

    The cons is that primitive would be the. same both for String and value representation. Still it works for my case.

    Still for toJSON this doesn't seem to work. So I keep on researching.


  2. Basically you want to overload properties to return different type values based on the getter’s call context.

    A short answer: SORRY that’s not C++ with type cast operator overloading.

    This pattern is basically absent in JS and I strongly don’t recommend it.

    You could try to overload though some way like this:

    'use strict';
    
    class Sub{
      #bucket = {};
      constructor(props){
        Object.assign(this, props);
      }
      get toString(){
        const out = () => {
          return Object.prototype.toString.call(this);
        }
        out.toString = () => this.#bucket.toString;
        return out;
      }
      set toString(val){
        this.#bucket.toString = val;
      }
    
    }
    
    const configRoot = {
      fluentSubSection: new Sub({
         toString: '[John Doe]',
         userProp:true
         })
    };
    
    console.log(configRoot.fluentSubSection);
    console.log(String(configRoot.fluentSubSection.toString));
    console.log(String(configRoot.fluentSubSection));
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search