Display accessor methods when an object is output in TypeScript

Is there a way in TypeScript/JavaScript to display an object's private properties using their getters instead of the actual property names?

For example, consider this TypeScript class:

class Vehicle {

  constructor(private _brand: string, private _year: number) {}

  get brand(): string {
    return this._brand;
  }

  get year(): number {
    return this._year;
  }

  set year(year: number) {
    this._year = year;
  }

  set brand(brand: string) {
    this._brand = brand;
  }
}

const vehicle: Vehicle = new Vehicle('Toyota', 10);

console.log(vehicle);

Currently, when logging the 'vehicle' object, you would see:

[LOG]: Vehicle: {
  "_brand": "Toyota",
  "_year": 10
} 

However, is it possible to achieve a log output like this:

[LOG]: Vehicle: {
  "brand": "Toyota",
  "year": 10
} 

Answer №1

The functionality of console.log can vary depending on the environment it's used in. To achieve the specific logging behavior you're looking for, you would need to create your own custom logger function. Here is an example of how such a function could be implemented in JavaScript:

function log(obj) {
    // Retrieve the names of getter properties defined on the prototype
    const ctor = obj.constructor;
    const proto = ctor?.prototype;
    const names = new Set(
        proto
            ? Object.entries(Object.getOwnPropertyDescriptors(proto))
                .filter(([_, {get}]) => !!get)
                .map(([name]) => name)
            : []
    );
    
    // Include the names of "own" properties that do not start with "_"
    for (const name of Object.keys(obj)) {
        if (!name.startsWith("_")) {
            names.add(name);
        }
    }
    
    // Create a simple object containing the values of those properties
    const simple = {};
    for (const name of names) {
        simple[name] = obj[name];
    }
    
    // Check if a "constructor" name exists for the object and include it if available
    let objName =
        obj[Symbol.toStringTag]
        || ctor?.name;
    if (objName) {
        simple[Symbol.toStringTag] = objName;
    }
    
    // Log the simplified object
    console.log(simple);
}

You can test this custom logger function using the live example provided below:

"use strict";

// Sample class definition for testing the log function
class Vehicle {
    constructor(_brand, _year) {
        this._brand = _brand;
        this._year = _year;
    }
    get brand() {
        return this._brand;
    }
    get year() {
        return this._year;
    }
    set year(year) {
        this._year = year;
    }
    set brand(brand) {
        this._brand = brand;
    }
}

// Creating an instance of the Vehicle class
const vehicle = new Vehicle('Toyota', 10);

// Logging the properties of the vehicle object using the log function
log(vehicle);

Feel free to customize and enhance the log function based on your specific requirements and preferences.

Answer №2

It may not be possible to achieve that directly, but one workaround could be defining a log function within the class as shown below:

  logger() {
    console.log({
      make: this.make,
	year: this.year,
    });
  }

You can then execute car.logger();

This will result in an output similar to {make: 'Toyota', year: 10}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on injecting configuration into forRoot

Is there a method to inject configuration object into AppModule's forRoot() function? How can I access the configService if there is no constructor within the module? config.yml: smtp: host: 'smtp.host.com' port: 10 secure: true aut ...

Using Vue to store form elements inside a component and accessing the data

Can someone help me decide if my approach makes sense? I may have gone overboard with components and now I'm questioning the benefits. I've created separate components for both the input field and send button in a form, but I'm facing challe ...

Incorporate server-side tags into client-side HTML and JavaScript scripts without the use of template engines

My goal is to carry out the following operation within client-side JavaScript from a file served using Node and Express: var rootURL = <%= "someurlfromserverconfig" %>; I am solely hosting a web directory from my Node app without any template engin ...

Finding alternative solutions without using the find() method when working with Angular

How can I use an equivalent to find(".class") in AngularJS? I came across this solution: //find('.classname'), assumes you already have the starting elem to search from angular.element(elem.querySelector('.classname')) I attempted to ...

Troubleshooting Jqgrid Keyboard Navigation Problem

Here is a link to the jsfiddle code snippet. Upon adding jQuery("#grid").jqGrid('sortableRows'); into my JavaScript code, I encountered an issue where keyboard navigation no longer worked after sorting rows Below is the JavaScript code snippet: ...

What is the best way to align these div elements within a table cell?

I am encountering an issue with the placement of elements. What I am striving for is something like this: https://i.stack.imgur.com/VSFXE.png where a div with several other divs inside is positioned at the top of the td, and another div is at the bottom o ...

Executing JavaScript following an Ajax request

I am faced with a situation where my HTML file utilizes a function for loading another PHP file using Ajax: function LoadContent(n,func) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange=function() { if (xm ...

Transforming the appearance of an Imagebutton upon clicking with the power of Javascript

I am attempting to update the image URL when a specific image button is clicked, however, I am encountering an issue where the image does not change. It seems that none of the JavaScript functions are successfully altering the image and are unable to iden ...

Using TypeScript: creating functions without defining an interface

Can function props be used without an interface? I have a function with the following properties: from - HTML Element to - HTML Element coords - Array [2, 2] export const adjustElements = ({ from, to, coords }) => { let to_rect = to.getBoundingC ...

Deleting the initial line in a JSON reply

My current code is : $.getJSON("https://www.domain.com/someapi/callback=?", function(data){ $.each(data, function(i,item){ alert(item.x); }); }); I am currently facing an issue with my JSON response because there is ...

Intentionally introduce discrepancies in the errors during validation of an object using hapi/joi

const validationSchema = Joi.object().keys({ Id: Joi.number().required(), CustomerName: Joi.string() .trim() .required() .when('$isInValidCustomer', { i ...

What causes an error when attempting to add a new user to the database?

Currently, I am delving into the world of Mongodb. To kick things off, I initiated by executing npm install --save mongoose uuid within the confines of Terminal. The primary objective of my project revolves around storing user information in the database. ...

Reset Angular's virtual scroll to the beginning of the list

Within my Angular application, I am utilizing the Virtual Scroll feature from the Angular cdk. Here is a snippet of my Component's template: <cdk-virtual-scroll-viewport itemSize="50" class="example-viewport"> <div *cdkVirtualFor="let ite ...

Exploring the Display of TextBox When an Alternative is Chosen from DropDownList on ASP.NET Web Forms

I am working on a project where I have an asp:DropDownList, and the requirement is that when the user selects "Other" from the list, a hidden TextBox should be displayed to the user. Initially, the TextBox is supposed to be hidden. To hide the TextBox whe ...

Patience is key when letting AJAX calls complete their execution in jQuery functions

In each of my 3 functions, I have a synchronous AJAX call. Here is an example: function() { a(); b(); c(); } a() { ajaxGet(globals.servicePath + '/Demo.svc/GetDemoList/' + sessionStorage.SessionId,function(data, success) {}, '&apos ...

Issue with the smooth scroll to top feature being unresponsive and not functioning

My attempt to create smooth scrolling to the top isn't going as planned. The code provided doesn't seem to be working, and the scrolling remains jumpy... $(function() { $('a[href*=#]').click(function() { if (location.pathname.r ...

When a large object changes value in Firebase, does it transfer only the delta change in internet bandwidth?

Hello, I am working with a node that contains an array of 1000 nodes, totaling around 60KB in size. rootRef.on('value', function (snapshot){ //callback every changes props , full list obj }); I would like to know: - When a node in ...

Tips for breaking down an item and removing a specific attribute?

I am attempting to break down an object and remove a specific property from it. Here is the current approach I am taking: let x = {a:1, b:2, c:3}; let y = {...x}; delete y.c; store.setState(y); I came across an article discussing ES7 that introduced ...

``What is the best way to transmit and capture data at the same time within Vue

Currently, I am working with the Laravel framework in conjunction with Vue. In my project, there is a parent component that contains a child component. The child component includes a list of checkboxes, and upon checking or unchecking any checkbox, the cor ...

Guidance on implementing a source map in a Node.js VM

Currently, I am analyzing JavaScript bundled source code in Node.js using the following snippet of code: const javascriptCode = "..." const javascriptSourceMap = "..." const wrapper = NativeModule.wrap(javascriptCode); const script = ne ...