Tari Ibaba

Tari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

The Complete Guide to JavaScript Symbols

In this article, we’re going to learn all about JavaScript symbols and how to use them in practice.

Creating symbols

The Symbol is a data type that was added to JavaScript in ES6. To create a symbol, you can use the global Symbol() function.

const sym1 = Symbol();

The Symbol() function accepts an optional string that serves as the description of the symbol.

const sym2 = Symbol('color');

const sym3 = Symbol('maxSpeed');

const sym4 = Symbol('age');

You can access this description with the description property of the Symbol. If no description was set, this property would be undefined.

console.log(sym1.description); // undefined

console.log(sym2.description); // color

console.log(sym3.description); // maxSpeed

console.log(sym4.description); // age

Every time you call the Symbol() function, it returns a new unique value.

console.log(Symbol() === Symbol()); // false

console.log(Symbol('color') === Symbol('color')); // false

console.log(Symbol('age') === Symbol('age')); // false

As a symbol is a primitive value, using the typeof operator on it will return a symbol string.

console.log(typeof sym1); // symbol

Trying to use the new operator to create a symbol will cause a TypeError. This prevents the creation of an explicit Symbol wrapper object in place of a new symbol value.

const num1 = Number(2);
console.log(typeof num1); // number

const num2 = new Number();
console.log(typeof num2); // object

const bool1 = Boolean(true);
console.log(typeof bool1); // boolean

const bool2 = new Boolean(true);
console.log(typeof bool2); // object

const sym1 = Symbol('color');
console.log(typeof sym1); // symbol

// ❌ TypeError
const sym2 = new Symbol('color');
console.log(typeof sym2);

Sharing symbols

ES6 comes with a global symbol registry that allows you to share symbols globally. To create a symbol for sharing, you use the Symbol.for() method instead of the Symbol() function. Symbol.for() takes a key and returns a symbol value from the registry.

For example:

const color = Symbol.for('color');

The Symbol.for() method first searches the global symbol registry for a symbol with the color key and returns it if it exists. Otherwise, Symbol.for() creates a new symbol, adds it to the registry with the specified color key, and returns the symbol.

Afterward, calling Symbol.for() with the same key returns this same symbol, as it now exists in the registry.

const carColor = Symbol.for('color');

console.log(color === carColor); // true

The Symbol.keyFor() method works together with Symbol.for() to retrieve information from the global symbol registry. You can get the key of a symbol that exists in the registry with Symbol.keyFor().

console.log(Symbol.keyFor(carColor)); // 'color'

If the key doesn’t exist, Symbol.keyFor() returns undefined.

const filename = Symbol('filename');

console.log(Symbol.keyFor(filename)); // undefined;

Uses of symbols

1. Enumerations

With symbols, we can define a group of constants to set a variable to a predefined set of values – an enumeration.

Let’s say we want to create a variable to store a value representing the day of the week. To create an enum, we could use strings like ‘Mon', 'Tue', 'Wed', etc.

const daysOfWeek = {
  Mon: 'Mon',
  Tue: 'Tue',
  Wed: 'Wed',
  Thu: 'Thu',
  Fri: 'Fri',
  Sat: 'Sat',
  Sun: 'Sun',
};

const dayOfWeek = daysOfWeek.Tue;

By using symbols in place of the string, we can ensure that the constants are always distinct from one another, and not worry about duplicate string values.

const daysOfWeek = {
  Mon: Symbol('Mon'),
  Tue: Symbol('Tue'),
  Wed: Symbol('Wed'),
  Thu: Symbol('Thu'),
  Fri: Symbol('Fri'),
  Sat: Symbol('Sat'),
  Sun: Symbol('Sun'),
};

const dayOfWeek = daysOfWeek.Tue;

2. Prevention of property name clashes

Since a symbol is always guaranteed to be unique, we can use it to avoid name clashes when entirely separate sections of code need to store data on an object. The different sections may not be aware of each other, but each wants to make sure that the property it uses is not going to be used by another.

For example:

// module-1.js

const module1 = () => {
  // Prevent external access with closure
  const module1Sym = Symbol();
  return (obj) => {
    // Put some data on obj that this module can access later
    obj[module1Sym] = 'module 1 data';
  };
};

// module-2.js

const module2 = () => {
  // Prevent external access with closure
  const module2Sym = Symbol();
  return (obj) => {
    // Put some data on obj that this module can access later
    obj[module2Sym] = 'module 2 data';
  };
};

// index.js

const obj = {};
module1(obj);
module2(obj);

If the modules each used a string instead of a symbol for the property name, it could cause problems as the names could clash.

For example:

// module-1.js

const module1 = () => {
  return (obj) => {
    // Put some data on obj that this module can access later
    obj.moduleData = 'module 1 data';
  };
};

// module-2.js

const module2 = () => {
  return (obj) => {
    // Put some data on obj that this module can access later
    obj.moduleData = 'module 2 data';
  };
};

// index.js

const obj = {};
module1(obj);
module2(obj);

// 'module 1 data' has been overwritten by the call the module2()

Note that symbol properties are not enumerable, if you call Object.keys() on the object, they will not be included in the array result.

const dayOfWeek = Symbol('dayOfWeek');
const event = {
  [dayOfWeek]: daysOfWeek.Tue,
  description: 'Birthday',
};

console.log(Object.keys(event)); // [ 'description' ]

Object.getOwnPropertyNames() returns an array of all the enumerable and non-enumerable properties of an object, but symbol properties are still excluded.

console.log(Object.getOwnPropertyNames(event)); // [ 'description' ]

To get all the symbol properties, you use the Object.getOwnPropertySymbols() method. This method returns an array of all symbol properties found directly on a given object.

console.log(Object.getOwnPropertySymbols(event)); // [ Symbol(dayOfWeek) ]

Well-known symbols

The Symbol class comes with static properties known as well-known symbols. They are used to implement and customize the behavior of certain built-in JavaScript operations.

Let’s explore some of these well-known symbols:

Symbol.hasInstance

The Symbol.hasInstance method customizes the behavior of the instanceof operator. Generally, when you use the instanceof operator like this:

obj instanceof type

JavaScript will call the Symbol.instanceof method like this:

type[Symbol.hasInstance](obj);

Here’s an example where we use the instanceof method on an instance of a user-defined class.

class List {}

console.log([] instanceof List); // false

Going by the default behavior of instanceof, [] is an Array, not an instance of the List class, so instanceof returns false here.

If we want to change this behavior and make instanceof return true in this scenario, we would customize the Symbol.hasInstance method like this:

class List {
  static [Symbol.hasInstance](obj) {
    return Array.isArray(obj);
  }
}

console.log([] instanceof List); // true

Symbol.iterator

With the Symbol.iterator method, we can specify if and how objects of a class can be iterated over. When this method is present, we will be able to use the for...of loop and spread syntax (...) on the objects of the class.

When you use the for...of loop on an array:

const numbers = [1, 2, 3];

for (const num of numbers) {
  console.log(num);
}

/*
1
2
3
*/

Internally, JavaScript first calls the Symbol.iterator method of the numbers array to get the iterator object. Then it continuously calls the next() method on the iterator object and copies the value property in the num variable, It exits the loop when the done property of the iterator object is true.

var iterator = numbers[Symbol.iterator]();

console.log(iterator.next()); // Object {value: 1, done: false}

console.log(iterator.next()); // Object {value: 2, done: false}

console.log(iterator.next()); // Object {value: 3, done: false}

console.log(iterator.next()); // Object {value: undefined, done: true}

By default, objects of a user-defined class are not iterable. But we can make them iterable with the Symbol.iterator method, as you’ll use in the following example:

class List {
  elements = [];

  add(element) {
    this.elements.push(element);
    return this;
  }

  // Generator
  *[Symbol.iterator]() {
    for (const element of this.elements) {
      yield element;
    }
  }
}

const colors = new List();
colors.add('red').add('blue').add('yellow');

// Works because of Symbol.iterator
for (const color of colors) {
  console.log(color);
}

/*
red
blue
yellow
*/

console.log([...colors]);
// [ 'red', 'blue', 'yellow' ]

Symbol.toStringTag

This symbol lets us customize the default string description of the object. It is used internally by the Object.prototype.toString() method.

class CarClass {
  constructor(color, maxSpeed, age) {
    this.color = color;
    this.maxSpeed = maxSpeed;
    this.age = age;
  }
}

const car = new CarClass('red', 100, 2);

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

Here is the default implementation of Symbol.toStringTag was outputted. Here’s how we can customize it:

class CarClass {
  constructor(color, maxSpeed, age) {
    this.color = color;
    this.maxSpeed = maxSpeed;
    this.age = age;
  }

  get [Symbol.toStringTag]() {
    return 'Car';
  }
}

const car = new CarClass('red', 100, 2);

console.log(Object.prototype.toString.call(car));
// [object Car]

Symbol.toPrimitive

The Symbol.toPrimitive method makes it possible for an object to be converted to a primitive value. It takes a hint argument that specifies the type of the resulting primitive value. This hint argument can be one of 'number', 'string', or 'default'.

Here’s an example of using the Symbol.toPrimitive method.

class Money {
  constructor(amount, currency) {
    this.amount = amount;
    this.currency = currency;
  }

  [Symbol.toPrimitive](hint) {
    if (hint === 'string') {
      return `${this.amount} ${this.currency}`;
    } else if (hint === 'number') {
      return this.amount;
    } else if (hint === 'default') {
      return `${this.amount} ${this.currency}`;
    }
  }
}

const price = new Money(500, 'USD');

console.log(String(price)); // 500 USD
console.log(+price); // 500
console.log('Price is ' + price); // Price is 500 USD

Conclusion

In this article, we learned how to create JavaScript symbols and share them in the global symbol registry. We saw the advantages of using symbols, and how well-known symbols can be used to customize the behavior of built-in JavaScript operations.

How to Get a File Name Without the Extension in Node.js

To get the name of a file without the extension in Node.js, use the parse() method from the path module to get an object representing the path. The name property of this object will contain the file name without the extension.

For example:

const path = require('path');

path.parse('index.html').name; // index

path.parse('package.json').name; // package

path.parse('image.png').name; // image

The parse() method

The parse() method returns an object with properties that represent the major parts of the given path. The object it returns has the following properties:

  1. dir – the directory of the path.
  2. root – the topmost directory in the operating system.
  3. base – the last portion of the path.
  4. ext – the extension of the file.
  5. name – the name of the file without the extension.
path.parse('C://Code/my-website/index.html');

/*
Returns:
{
  root: 'C:/',
  dir: 'C://Code/my-website',
  base: 'index.html',
  ext: '.html',
  name: 'index'
}
*/

If the path is not a string, parse() throws a TypeError.

// ❌ TypeError: Received type of number instead of string
path.parse(123).name;

// ❌ TypeError: Received type of boolean instead of string
path.parse(false).name;

// ❌ TypeError: Received type of URL instead of string
path.parse(new URL('https://example.com/file.txt')).name;

// βœ… Received correct type of string
path.parse('index.html').name; // index

How to Get a File Extension in Node.js

To get the extension of a file in Node.js, we can use the extname() method from the path module.

For example:

const path = require('path');

path.extname('style.css') // .css

path.extname('image.png') // .png

path.extname('prettier.config.js') // .js

The extname() method

The extname() method returns the extension of the given path from the last occurrence of the . (period) character to the end of the string in the last part of the path.

If there is no . in the last part of the path, or if the path starts with . and it is the only . character in the path, extname() returns an empty string.

path.extname('index.'); // .

path.extname('index'); // '' (empty string)

path.extname('.index');   // '' (empty string)

path.extname('.index.html'); // .html

If the path is not a string, extname() throws a TypeError.

const path = require('path');

// ❌ TypeError: Received type number instead of string
path.extname(123);

// ❌ TypeError: Received type boolean instead of string
path.extname(false);

// ❌ TypeError: Received URL instance instead of string
path.extname(new URL('https://example.com/file.txt'));

// βœ… Received type of string
path.extname('package.json'); // .json

How to Subtract 30 Days From the Current Date in JavaScript

1. Date setDate() and getDate() methods

To subtract 30 days from the current date in JavaScript:

  1. Use the Date() constructor to create a new Date object with the current date.
  2. Call the getDate() method on this object to get the days.
  3. Subtract 30 from the return value of getDate().
  4. Pass the result of the subtraction to the setDate() method.
// Current date: September 29, 2022
const date = new Date();

date.setDate(date.getDate() - 30);

// New date: August 30, 2022
console.log(date);

The Date getDate() method returns a number between 1 and 31 that represents the day of the month of the particular Date.

The Date setDate() method changes the day of the month of the Date object to the number passed as an argument.

If the days you specify would change the month or year of the Date, setDate() automatically updates the Date information to reflect this.

// April 25, 2022
const date = new Date('2022-04-25T00:00:00.000Z');

date.setDate(40);

// May 10, 2022
console.log(date); // 2022-05-10T00:00:00.000Z

console.log(date.getDate()); // 10

April has only 30 days, so passing 40 to setDate() here increments the month by one and sets the day of the month to 10.

2. date-fns subDays() function

Alternatively, we can use the subDays() function from the date-fns NPM package to subtract 30 days from the current date. subDays() takes a Date object and the number of days to subtract as arguments. It returns a new Date object with the days subtracted.

import { subDays } from 'date-fns';

// Current date: September 29, 2022
const date = new Date();

const newDate = subDays(date, 30);

// New date: August 30, 2022
console.log(newDate);

Note that subDays() returns a new Date object without mutating the one passed to it.

How to Subtract Days From a Date in JavaScript

1. Date setDate() and getDate() methods

To subtract days from a Date in JavaScript:

  1. Call the getDate() method on the Date to get the days.
  2. Subtract the days.
  3. Pass the result of the subtraction to the setDate() method.

For example:

function subtractDays(date, days) {
  date.setDate(date.getDate() - days);

  return date;
}

// May 15, 2022
const date = new Date('2022-05-15T00:00:00.000Z');

const newDate = subtractDays(date, 5);

// May 10, 2022
console.log(newDate); // 2022-05-10T00:00:00.000Z

Our subtractDays() function takes a Date object and the number of days to subtract as arguments. It returns the same Date object with the days subtracted.

The Date getDate() method returns a number between 1 and 31 that represents the day of the month of the particular Date.

The Date setDate() method changes the day of the month of the Date object to the number passed as an argument.

If the days you specify would change the month or year of the Date, setDate() automatically updates the Date information to reflect this.

// April 25, 2022
const date = new Date('2022-04-25T00:00:00.000Z');

date.setDate(40);

// May 10, 2022
console.log(date); // 2022-05-10T00:00:00.000Z

console.log(date.getDate()); // 10

April has only 30 days, so passing 40 to setDate() here increments the month by one and sets the day of the month to 10.

Avoiding Side Effects

The setDate() method mutates the Date object it is called on. This introduces a side effect into our subtractDays() function. To avoid modifying the passed Date and create a pure function, make a copy of the Date and call setDate() on this copy, instead of the original.

function subtractDays(date, days) {
  // πŸ‘‡ Make copy with "Date" constructor
  const dateCopy = new Date(date);

  dateCopy.setDate(dateCopy.getDate() - days);

  return dateCopy;
}

const date = new Date('2022-05-15T00:00:00.000Z');

const newDate = subtractDays(date, 5);

console.log(newDate); // 2022-05-10T00:00:00.000Z

// πŸ‘‡ Original not modified
console.log(date); // 2022-05-15T00:00:00.000Z

Tip: Functions that don’t modify external state (i.e., pure functions) tend to be more predictable and easier to reason about, as they always give the same output for a particular input. This makes it a good practice to limit the number of side effects in your code.

2. date-fns subDays() function

Alternatively, we can use the subDays() function from the date-fns NPM package to quickly subtract days from a Date. It works like our pure subtractDays() function.

import { subDays } from 'date-fns';

const date = new Date('2022-05-15T00:00:00.000Z');

const newDate = subDays(date, 5);

console.log(newDate); // 2022-05-10T00:00:00.000Z

// Original not modified
console.log(date); // 2022-05-15T00:00:00.000Z

How to Get the Value of an Input When the Enter Key is Pressed in React

To get the value of an input when the Enter key is pressed in React:

  1. Create a state variable to store the value of the input.
  2. Set an onChange event handler on the input to update the state variable when the input field value changes.
  3. Set an onKeyDown event handler on the input.
  4. Use the state variable to access the input value in the event handler, after checking that the key pressed is Enter.

For example:

App.js

import { useState } from 'react';

export default function App() {
  const [message, setMessage] = useState('');

  const [updated, setUpdated] = useState('');

  const handleChange = (event) => {
    setMessage(event.target.value);
  };

  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      // πŸ‘‡ Get input value
      setUpdated(message);
    }
  };

  return (
    <div>
      <input
        type="text"
        id="message"
        name="message"
        value={message}
        onChange={handleChange}
        onKeyDown={handleKeyDown}
      />

      <h2>Message: {message}</h2>

      <h2>Updated: {updated}</h2>
    </div>
  );
}
Getting an input value when the Enter key is pressed.

With the useState() hook we create a state variable (message) to store the current value of the input field. We also create another state variable (updated) that will be updated with the input field value when the Enter key is pressed.

We set an onChange event handler on the input field to make this handler get called whenever the input value changes. In the handler we use the target property of the event object to access the object that represents the input element. The value property of this object contains the input value, so we pass it to setMessage() to update message, and this reflects on the page.

After setting up the controlled input, we can now use message outside the handleChange handler to access the current value of the input field.

We use the event.key property to get the key pressed in the onKeyDown event handler. After ensuring that this key is Enter, we use setUpdated(message) to update the updated variable with the current input field value.

Get input value on Enter with event.target

We can also get the value of the input when the Enter key is pressed using the target.value property of the Event object. This is useful in cases where we are not tracking the input value with a state variable, i.e., an uncontrolled input.

import { useState } from 'react';

export default function App() {
  const [updated, setUpdated] = useState('');

  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      setUpdated(event.target.value);
    }
  };

  return (
    <div>
      <input
        type="text"
        id="message"
        name="message"
        onKeyDown={handleKeyDown}
      />

      <h2>Updated: {updated}</h2>
    </div>
  );
}
Getting an input value when the Enter key is pressed.

Get input value on Enter with ref

We can also use a ref to get the value of an uncontrolled input when the Enter key is pressed.

import { useRef, useState } from 'react';

export default function App() {
  const inputRef = useRef(null);

  const [updated, setUpdated] = useState('');

  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      setUpdated(inputRef.current.value);
    }
  };

  return (
    <div>
      <input
        ref={inputRef}
        type="text"
        id="message"
        name="message"
        onKeyDown={handleKeyDown}
      />

      <h2>Updated: {updated}</h2>
    </div>
  );
}

While the data in a controlled input is handled by React state, the data in an uncontrolled input is handled by the DOM itself. This is why the input in the example above doesn’t have a value prop or onChange event handler set. Instead, we access the input field value with a React ref. The DOM updates this value when the text in the input is changed.

We create a ref object with the useRef() hook and set it to the ref prop of the input. Doing this sets the current property of the ref object to the DOM object that represents the input element.

useRef() returns a mutable ref object that does not change value when a component is updated. Also, modifying the value of this object’s current property does not cause a re-render. This is in contrast to the setState update function returned from useState().

Although the React documentation recommends using controlled components, uncontrolled components offer some advantages. You might prefer them if the form is very simple and doesn’t need instant validation, and values only need to be accessed when the form is submitted.

How to Get the Value of an Input When a Button is Clicked in React

Related: How to Get an Input Field’s Value in React

To get the value of an input field on button click in React:

  1. Create a state variable to store the value of the input field.
  2. Set an onChange event handler on the input to update the state variable when the input field value changes.
  3. Set an onClick event handler on a button element.
  4. Access the state variable in the event handler.

For example:

App.js

import { useState } from 'react';

export default function App() {
  const [message, setMessage] = useState('');

  const [updated, setUpdated] = useState(message);

  const handleChange = (event) => {
    setMessage(event.target.value);
  };

  const handleClick = () => {
    // πŸ‘‡ "message" stores input field value
    setUpdated(message);
  };

  return (
    <div>
      <input
        type="text"
        id="message"
        name="message"
        onChange={handleChange}
        value={message}
      />

      <h2>Message: {message}</h2>

      <h2>Updated: {updated}</h2>

      <button onClick={handleClick}>Update</button>
    </div>
  );
}
Getting the input value on button click.

With the useState() hook we create a state variable (message) to store the current value of the input field. We also create another state variable (updated) that will be updated with the input field value when the button is clicked.

We set an onChange event handler on the input field to make this handler get called whenever the input value changes. In the handler, we use the event.target property to access the object representing the input element. The value property of this object contains the input value, so we pass it to setMessage() to update message, and this reflects on the page.

After setting up the controlled input, we can now use message outside the handleChange handler to access the current value of the input field.

So in the onClick event handler we set on the button, we use setUpdated(message) to update the updated variable with the current input field value.

Get value of uncontrolled input on button click

To get the value of an uncontrolled input on button click in React:

  1. Create a ref for the input field
  2. Set an onClick event handler on the button.
  3. Use the ref object to access the current input value in the event handler.

For example:

App.js

import { useRef, useState } from 'react';

export default function App() {
  const inputRef = useRef(null);

  const [updated, setUpdated] = useState('');

  const handleClick = () => {
    // πŸ‘‡ "inputRef.current.value" is input value
    setUpdated(inputRef.current.value);
  };

  return (
    <div>
      <input
        ref={inputRef}
        type="text"
        id="message"
        name="message"
      />

      <h2>Updated: {updated}</h2>

      <button onClick={handleClick}>Update</button>
    </div>
  );
}
Updating text with the value of an input field on button click.

While the data in a controlled input is handled by React state, the data in an uncontrolled input is handled by the DOM itself. This is why the input in the example above doesn’t have a value prop or onChange event handler set. Instead, we access the input field value with a React ref. The DOM updates this value when the text in the input is changed.

We create a ref object with the useRef() hook and set it to the ref prop of the input. Doing this sets the current property of the ref object to the DOM object that represents the input element.

useRef() returns a mutable ref object that does not change value when a component is updated. Also, modifying the value of this object’s current property does not cause a re-render. This is in contrast to the setState update function returned from useState().

Although the React documentation recommends using controlled components, uncontrolled components offer some advantages. You might prefer them if the form is very simple and doesn’t need instant validation, and values only need to be accessed when the form is submitted.

How to Fix the “Cannot Find name ‘describe'” Error in TypeScript

To fix the “cannot find name ‘describe'” error, install the type definitions for your testing framework, and then add the definitions to the types array in your tsconfig.json file.

This error happens if you try to use the describe() function in a TypeScript file, but type definitions for the package are missing.

The "cannot find name 'describe'" error happening in a TypeScript file in VS Code.
index.ts
/* Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i --save-dev @types/jest` or `npm i --save-dev @types/mocha`. ts(2582) */ describe('example', () => { it('adds two numbers together', () => { expect(2 + 2).toBe(4); }); }); ο»Ώ

Install the type definitions for the testing framework you’re using by running one of the following commands at the root of your project directory.

Shell
# πŸ‘‡ Jest npm i -D @types/jest jest # πŸ‘‡ Mocha npm i -D @types/mocha mocha # Yarn # πŸ‘‡ Jest yarn add --dev @types/jest jest # πŸ‘‡ Mocha yarn add --dev @types/mocha mocha

Add typings to types array in tsconfig.json

In some cases, this is all you need to fix the error. But if it persists, you might need to add the newly installed typings to the types array of your tsconfig.json file.

So if you’re using Jest, you’ll add a jest string to the types array, and then your tsconfig.json file will look something like this:

tsconfig.json
{ "compilerOptions": { "types": [ // ... other types "jest" ] // ..other settings } }

If you’re using Mocha too, you’ll add a mocha string to the types array.

tsconfig.json
{ "compilerOptions": { "types": [ // ... other types "mocha" ] // ..other settings } }

Include test files

If the error still doesn’t go away after doing this, make sure that TypeScript is not ignoring the directory containing your test files.

If you’ve set the include array in your tsconfig.json file, make sure the patterns specified in this array match the directory where your test files are located.

For example, if your test files are located in a src directory, TypeScript will detect them with a configuration like this:

tsconfig.json
{ "compilerOptions": {}, "include": ["src/**/*"], }

But if they’re located in a tests directory, we’ll need to add an additional glob pattern to make TypeScript detect them:

tsconfig.json
{ "compilerOptions": {}, "include": [ "src/**/*", "tests/**/*" ], }

We can also include glob patterns to match files with a specific ending or extension.

For example, we can include all files ending with .spec.ts and .test.ts with this config:

tsconfig.json
{ "compilerOptions": {}, "include": [ "src/**/*", "**/*.spec.ts", "**/*.test.ts" ], }

If you’ve set the exclude array in your tsconfig.json file, make sure that none of the patterns in the array match the directory containing the test files, as this will prevent TypeScript from detecting them.

For example, in the tsconfig.json file below, files ending with .spec.ts have been excluded, so TypeScript will ignore them and the error will occur when you attempt to use describe() in them.

tsconfig.json
{ "compilerOptions": {}, "include": [ "src/**/*" ], "exclude": [ "**/*.test.ts" ], }

We’ll fix this issue by simply moving the pattern string from exclude to include:

tsconfig.json
{ "compilerOptions": {}, "include": [ "src/**/*", "**/*.test.ts" ], }

Import module in file

Instead of adding the typings to the types array, you can also import them at the top of the file where you are using describe().

So if we’re using Jest, we’ll add an import 'jest' line at the beginning of the file.

index.ts
// πŸ‘‡ import 'jest'; // βœ… No error describe('example', () => { it('adds two numbers together', () => { expect(2 + 2).toBe(4); }); }); ο»Ώ

If we’re also using Mocha, we’ll add an import 'mocha' line:

index.ts
// πŸ‘‡ import 'mocha'; // βœ… No error describe('example', () => { it('adds two numbers together', () => { expect(2 + 2).toBe(4); }); }); ο»Ώ

Restart IDE

If the error persists after doing all of this, restarting your IDE might help.

How to Remove a DOM Element OnClick in JavaScript

To remove an element from the DOM onclick in JavaScript:

  1. Select the DOM element with a method like getElementById().
  2. Add a click event listener to the element.
  3. Call the remove() method on the element in the event handler.
const element = document.getElementById('el');

element.remove();

Consider this sample HTML where we create a blue box.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>
    <style>
      #box {
        height: 100px;
        width: 100px;
        background-color: blue;
      }
    </style>
  </head>
  <body>
    Click the box to remove it.

    <div id="box"></div>

    <script src="index.js"></script>
  </body>
</html>

Here’s how we can cause the element to be removed when it is clicked.

index.js

const box = document.getElementById('box');

box.addEventListener('click', () => {
  box.remove();
});
Clicking the element removes it from the DOM.

We used the addEventListener() method to add a handler for the click event to the #box element. This event handler will be called whenever the user clicks the box.

In the handler function, we called the remove() method on the element to remove it from the DOM.

We could also have used the target property on the event object passed to the handler to remove the element.

const box = document.getElementById('box');

box.addEventListener('click', (event) => {
  event.target.remove();
});

We can use the event object to access useful information and perform certain actions related to the event. For the click event, the target property lets us access the DOM element that was clicked.

Removing the element with the target property is useful when we want to dynamically remove many elements onclick. For example:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>
    <link rel="stylesheet" href="index.css" />
  </head>
  <body>
    Click on a box to remove it.

    <div class="container">
      <div class="box" id="box-1"></div>
      <div class="box" id="box-2"></div>
      <div class="box" id="box-3"></div>
    </div>

    <script src="index.js"></script>
  </body>
</html>

index.css

.container {
  display: flex;
}

.box {
  height: 100px;
  width: 100px;
  margin: 5px;
}

#box-1 {
  background-color: blue;
}

#box-2 {
  background-color: red;
}

#box-3 {
  background-color: green;
}

index.js

const boxes = document.getElementsByClassName('box');

for (const box of boxes) {
  box.addEventListener('click', (event) => {
    event.target.remove();
  });
}
Clicking on any one of the elements removes it.

We can also remove any one of the elements onclick by adding a single event listener to the parent of all the elements.

index.js

const container = document.querySelector('.container');

container.addEventListener('click', (event) => {
  event.target.remove();
});

This is because the target property returns the innermost element in the DOM that was clicked. This is in contrast to the event.currentTarget property, which returns the element that the event listener was added to.

How to Link an Image in React

Related: How to Use an Image as a Link in React

To link a local image in React, import the image at the top of the file and assign it to the src prop of an img element.

For example:

App.js

// πŸ‘‡ import image from file
import myImage from './my-image.jpg';

export default function App() {
  return (
    <div>
      {/* πŸ‘‡ show image */}
      <img src={myImage} alt="Trees" height="200" />

      <br />

      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}
Linking and displaying an image on the webpage.
Linking and displaying an image on the webpage.

This approach works when using a Webpack-based tool like Create React App.

Note that the image file must be within the project directory to be imported successfully. An error will occur if the file is outside the project directory.

Alternatively, we can use the require() function to link an image in React.

The following code example will produce precisely the same result on the page as the first example.

App.js

export default function App() {
  return (
    <div>
      {/* πŸ‘‡ */}
      <img
        src={require('./my-image.jpg')}
        alt="Trees"
        height="200"
      />

      <br />
      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}

The advantage require() has here is that it doesn’t need to be at the top of the page. We can simply assign the result of require() to the src prop without having to store it in a variable.

Another way to link an image in React is to place it in the public folder and reference it with its relative path.

For example, if we placed the my-image.png file in the public folder, we’ll be able to display it in the page like this:

App.js

export default function App() {
  return (
    <div>
      {/* πŸ‘‡ show image */}
      <img src="./my-image.jpg" alt="Trees" height="200" />

      <br />

      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}

Using the public folder is advantageous when we have many images that we want to display dynamically.

In the following examples, we dynamically display 100 images placed in a grid subfolder under public, and named with a certain pattern (image-1.jpg, image-2.jpg, …, image-100.png) in a grid.

App.js

export default function App() {
  return (
    <div>
      <div
        style={{
          display: 'grid',
          gridTemplateColumns:
            'repeat(auto-fit, minmax(min-content, 250px))',
          gap: '8px',
        }}
      >
        {[...Array(100)].map((_, i) => {
          return (
            <div>
              {/* πŸ‘‡ linking images dynamically */}
              <img
                key={i}
                src={`./grid/image-${i + 1}.jpg`}
                style={{ width: '100%', height: 'auto' }}
              />
            </div>
          );
        })}
      </div>
    </div>
  );
}

If the image is stored online, then we’ll just have to set the URL of the image to the src prop to link and display it, like we do in plain HTML.

App.js

export default function App() {
  return (
    <div>
      {/* πŸ‘‡ show remote image */}
      <img
        src="http://example.com/trees/my-image.jpg"
        alt="Trees"
        height="200"
      />

      <br />

      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}