0

I have an interface and a class as follows

export interface ISample {
  propA: string;
  propB: string;
}

export class Sample {
  
  private props = {} as ISample;

  public get propA(): string {
    return this.props.propA;
  }

  public set propA(propA: string) {
    this.props.propA = propA;
  }

  public get propB(): string {
    return this.props.propB;
  }

  public set propB(propB: string) {
    this.props.propB = propB;
  }

}

In my code, I use the class to initialize the object as follows.

let sample = new Sample();
sample.propA = 'A';
sample.propB = 'B';

But when I try printing the object using console.log(sample), I get

props: {propsA: "A", propsB: "B"}
propsA: (...)
propsB: (...)

How do I get the output to display only {propsA: "A", propsB: "B"} when I use console.log(sample)?

PS : I am using typescript 3.8.3 with Angular 9.

Jaseem Abbas
  • 5,028
  • 6
  • 48
  • 73

4 Answers4

1

Seeing that you wish to use the properties directly without any class object instances in between, you could skip the Sample class altogether. Instead you could try to use the ISample interface directly.

Try the following

export interface ISample {
  propA: string;
  propB: string;
}

export class AppComponent  {
  sample = {} as ISample;

  ngOnInit() {
    this.sample.propA = 'A';
    this.sample.propB = 'B';

    // prints {propA: "A", propB: "B"}
    console.log(this.sample);
  }
}
ruth
  • 29,535
  • 4
  • 30
  • 57
0

Your class Sample has a class property called sample which inherits ISample. That said it's obvious you're getting that log of props: { propA: "A", propB: "B"}.

If you want propA and propB to be direct elements of your class you've to inherit the Interface properly. Doing so, you'll have to set propA and propB as direct elements of Sample which leads to your desired log.

export class Sample implements ISample {
  propsA = '';
  propsB = '';
}

Keep in mind you've to adjust your setters and getters accordingly as long as you're using private states.

Aer0
  • 3,792
  • 17
  • 33
0

You can override the toString() method:

export interface ISample {
  propA: string;
  propB: string;
}

export class Sample {
  
  props = {} as ISample;

  public get propA(): string {
    return this.props.propA;
  }

  public set propA(propA: string) {
    this.props.propA = propA;
  }

  public get propB(): string {
    return this.props.propB;
  }

  public set propB(propB: string) {
    this.props.propB = propB;
  }

  toString() {
    return this.props;
  }
}

let sample = new Sample();
sample.propA = 'A';
sample.propB = 'B';

console.log(sample.props)
Florian
  • 385
  • 6
  • 13
0

There is very little you can do to change the display of the class via console.log. This function is implemented in the browser and leaves little room to manouver. For example implementation in FF

function log(aThing) {
  if (aThing === null) {
    return "null\n";
  }

  if (aThing === undefined) {
    return "undefined\n";
  }

  if (typeof aThing == "object") {
    let reply = "";
    let type = getCtorName(aThing);
    if (type == "Map") {
      reply += "Map\n";
      for (let [key, value] of aThing) {
        reply += logProperty(key, value);
      }
    }
    else if (type == "Set") {
      let i = 0;
      reply += "Set\n";
      for (let value of aThing) {
        reply += logProperty('' + i, value);
        i++;
      }
    }
    else if (type.match("Error$") ||
             (typeof aThing.name == "string" &&
              aThing.name.match("NS_ERROR_"))) {
      reply += "  Message: " + aThing + "\n";
      if (aThing.stack) {
        reply += "  Stack:\n";
        var frame = aThing.stack;
        while (frame) {
          reply += "    " + frame + "\n";
          frame = frame.caller;
        }
      }
    }
    else if (aThing instanceof Components.interfaces.nsIDOMNode && aThing.tagName) {
      reply += "  " + debugElement(aThing) + "\n";
    }
    else {
      let keys = Object.getOwnPropertyNames(aThing);
      if (keys.length > 0) {
        reply += type + "\n";
        keys.forEach(function(aProp) {
          reply += logProperty(aProp, aThing[aProp]);
        });
      }
      else {
        reply += type + "\n";
        let root = aThing;
        let logged = [];
        while (root != null) {
          let properties = Object.keys(root);
          properties.sort();
          properties.forEach(function(property) {
            if (!(property in logged)) {
              logged[property] = property;
              reply += logProperty(property, aThing[property]);
            }
          });

          root = Object.getPrototypeOf(root);
          if (root != null) {
            reply += '  - prototype ' + getCtorName(root) + '\n';
          }
        }
      }
    }

    return reply;
  }

  return "  " + aThing.toString() + "\n";
}

As you can see, for class instances (typeof aThing == "object") it calls Object.getOwnPropertyNames and displays every property.

Note that toString won't help - it is not used for objects (with typeof aThing == "object")

Similarly, V8ValueStringBuilder.append in Chrome

if (value->IsObject() && !value->IsDate() && !value->IsFunction() &&
        !value->IsNativeError() && !value->IsRegExp()) {
    v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
    v8::Local<v8::String> stringValue;
    if (object->ObjectProtoToString(m_context).ToLocal(&stringValue))
        return append(stringValue);
}
/**
  * Call builtin Object.prototype.toString on this object.
  * This is different from Value::ToString() that may call
  * user-defined toString function. This one does not.
  */
 V8_WARN_UNUSED_RESULT MaybeLocal<String> ObjectProtoToString(
     Local<Context> context);

See also: Does console.log invokes toString method of an object?

Lesiak
  • 22,088
  • 2
  • 41
  • 65