Lessons from open-source: Use Symbol in Javascript to avoid name collisions

Lessons from open-source: Use Symbol in Javascript to avoid name collisions

This lesson is picked from next.js/packages/next. In this article, you will learn what a Symbol is, how Next.js uses Symbol, some other repositories that use Symbol in the Github wilderness and further reading references

What is a Symbol in Javascript?

In JavaScript, a Symbol is a unique and immutable data type introduced in ECMAScript 6 (ES6). Unlike other primitive data types like strings or numbers, Symbols are guaranteed to be unique, making them useful for creating keys in objects that need to avoid naming collisions. Symbols can be used to define properties with special meanings or to create private members within objects (But they are not entirely private, you can access symbols using Object.getOwnPropertySymbols).

Example:

// Creating a Symbol
const mySymbol = Symbol('uniqueSymbol');
// Using the Symbol as a property key
const myObject = {
[mySymbol]: 'This is a value associated with mySymbol',
};
// Accessing the property using the Symbol
console.log(myObject[mySymbol]); // Output: This is a value associated with mySymbol
console.log("Object.getOwnPropertySymbols", Object.getOwnPropertySymbols);

Practice the exercises based on documentation to become an expert in Next.js

How Next.js uses Symbol

  1. To avoid name collision with a helper function next.js/packages/next/server/next.ts
private async [SYMBOL_LOAD_CONFIG]() {
    const dir = resolve(this.options.dir || '.')

    const config =
      this.options.preloadedConfig ||
      (await loadConfig(
        this.options.dev ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_SERVER,
        dir,
        {
          customConfig: this.options.conf,
          silent: true,
        }
      ))

    // check serialized build config when available
    if (process.env.NODE_ENV === 'production') {
      try {
        const serializedConfig = require(path.join(
          dir,
          '.next',
          SERVER_FILES_MANIFEST
        )).config

        // @ts-expect-error internal field
        config.experimental.isExperimentalCompile =
          serializedConfig.experimental.isExperimentalCompile
      } catch (_) {
        // if distDir is customized we don't know until we
        // load the config so fallback to loading the config
        // from next.config.js
      }
    }

    return config
  }

  private async getServer() {
    if (!this.serverPromise) {
      this.serverPromise = this[SYMBOL_LOAD_CONFIG]().then(async (conf) => {
        if (this.standaloneMode) {
          process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(conf)
        }

2. To avoid keys collision in req

req object obviously has a lot of properties, the safe way to add additional properties is using Symbol

Where else you find Symbol used

You can also search for “Symbol” on Github with a language filter set to Javascript, you will find some popular repositories that use Symbol in their codebase.

As you can see, it is well known data type used in popular repos such as webpack, svelte, mongo etc.,

Further Reading References:

  1. MDN documentation

  2. https://stackoverflow.com/questions/21724326/what-is-the-motivation-for-bringing-symbols-to-es6

Conclusion:

In conclusion, Symbols in JavaScript are unique and immutable data types introduced in ECMAScript 6 (ES6). Unlike other primitive data types, Symbols guarantee uniqueness, making them useful for creating keys in objects to avoid naming collisions. Next.js uses Symbols to prevent name collisions with helper functions and keys.

Practice the exercises based on documentation to become an expert in Next.js

Make sure to follow me for more lessons from opensource.