How Symbol.toStringTag Works in JavaScript

Symbol.toStringTag is a built-in well-known JavaScript symbol used to customize the string description returned by Object.prototype.toString(). By assigning a string value to this symbol on an object or class prototype, developers can replace the default generic tag—such as "[object Object]"—with a custom tag like "[object MyCustomClass]". This article explains how the default string tagging mechanism works, how to implement Symbol.toStringTag in objects and classes, and how JavaScript uses it internally for type identification.

The Default Behavior of Object.prototype.toString

In JavaScript, invoking Object.prototype.toString.call(value) is a classic method used to reliably inspect an object’s internal [[Class]] or type.

By default, built-in types produce recognizable tags:

Object.prototype.toString.call([1, 2, 3]); // "[object Array]"
Object.prototype.toString.call(new Map());  // "[object Map]"
Object.prototype.toString.call(new Date()); // "[object Date]"

However, user-defined objects and class instances resolve to a generic tag by default:

class User {}
const user = new User();

console.log(Object.prototype.toString.call(user)); // "[object Object]"

How Symbol.toStringTag Overrides the Default Tag

When Object.prototype.toString() executes, it checks whether the target object contains a property keyed by Symbol.toStringTag. If the property exists and its value is a string, Object.prototype.toString() uses that string inside the brackets instead of the default "Object".

Using Symbol.toStringTag with Plain Objects

You can define Symbol.toStringTag directly on an object literal:

const customConfig = {
  [Symbol.toStringTag]: "AppConfig",
  apiUrl: "https://api.example.com",
};

console.log(Object.prototype.toString.call(customConfig)); 
// Output: "[object AppConfig]"

Using Symbol.toStringTag with Classes

When working with ES6 classes, the standard practice is to implement Symbol.toStringTag as a getter on the class prototype:

class DatabaseConnection {
  get [Symbol.toStringTag]() {
    return "DatabaseConnection";
  }
}

const db = new DatabaseConnection();

console.log(Object.prototype.toString.call(db)); 
// Output: "[object DatabaseConnection]"

Built-In Usage in JavaScript

Modern JavaScript engines use Symbol.toStringTag internally across many built-in APIs to standardize their type descriptions:

console.log(Math[Symbol.toStringTag]);                  // "Math"
console.log(Promise.resolve()[Symbol.toStringTag]);    // "Promise"
console.log(new Set()[Symbol.toStringTag]);            // "Set"
console.log(Object.prototype.toString.call(new Set())); // "[object Set]"

Key Considerations