typescript

How to Fix the “Unexpected reserved word ‘enum'” Error in JavaScript

The “Unexpected reserved word ‘enum'” syntax error happens in JavaScript happens because enum is not a valid keyword in JavaScript, but it is reserved.

The "Unexpected reserved word 'enum'" syntax error happening in JavaScript.

It was reserved in the ECMAScript specification in case it may become valid in the future.

If it wasn’t reserved, devs could start using it as variable names in their code – making future keyword use impossible!

JavaScript
// ❌ SyntaxError: Unexpected reserved word 'enum' enum Color { Red, Blue, Green } const color = Color.Red;

To fix it, represent the enumeration in another way, or change the file to TypeScript.

Fix: Create a JavaScript enum the right way

Enums are useful stuff, but since there’s no enum keyword in JS, we’ll have to find others way to create and use them.

One powerful way to create an enumeration is with an object with JavaScript symbol properties:

JavaScript
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;

With JavaScript symbols, we make sure that the constants are always different values, as every symbol is unique.

No need to worry duplicates – pretty convenient, right?

If we used this:

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

Someone could easily reassign the object’s properties to something else, giving us something more to worry about.

Fix: Just use TypeScript

Ah, TypeScript.

Alway there for us. Filled to the top with juicy modern stuff.

I mean enums aren’t so modern, but it’s one thing TS has that JS doesn’t.

Our first JS code runs flawlessly in TypeScript.

TypeScript
// ✅ No error - enums all the way! enum Color { Red, Blue, Green } const color = Color.Red;

So, if you really need that enum keyword – even though much of the TypeScript community seems to frown on it – change that file extension.

Oh, it could even be that it’s TypeScript you wanted all along. As it happened here.

Here, this person was new to TypeScript on Node (we’ll all been there) and ran his TS file with the node command directly.

Well, Node didn’t care about the extension and just treated the entire thing like a JavaScript file.

The easy solution was to compile it first with tsc before running node on the JS output. Or to use ts-node on the TypeScript file directly.

Key takeaways

So, the few things to keep in mind on fixing the “Unexpected reserved keyword ‘enum'” error in JavaScript:

  1. enum is a no-go in JavaScript (for now): JavaScript doesn’t have enum. It’s reserved for future use.
  2. Use objects with symbol properties: Want to create enumerations in JavaScript? Use objects with symbol properties.
  3. Symbols keep your code safe: Symbols are unique. They stop others from messing with your object’s properties.
  4. TypeScript has enum: Need enum? Switch to TypeScript. It’s got your back.
  5. Remember to compile TypeScript: Using TypeScript for Node.js? Compile your TypeScript files first. Or quickly use ts-node.

How to Quickly Get the Current Route in Next.js

We can get the current route in a Next.js component with the useRouter hook:

src/pages/index.tsx
import Head from 'next/head'; import { useRouter } from 'next/router'; export default function Home() { const { pathname } = useRouter(); return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Next.js Tutorials by Coding Beauty" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.ico" /> </Head> <main> Welcome to Coding Beauty 😄 <br /> <br /> Pathname: <b>{pathname}</b> <br /> URL: <b>{currentUrl}</b> </main> </> ); }
Displaying the current route on a Next.js page

Get current route in Next.js app router component

To get the current route in a Next.js app router component, you can use the usePathname hook from next/navigation.

src/app/page.tsx
'use client'; import React from 'react'; import { Metadata } from 'next'; import { usePathname } from 'next/navigation'; export const metadata: Metadata = { title: 'Next.js - Coding Beauty', description: 'Next.js Tutorials by Coding Beauty', }; export default function Page() { const pathname = usePathname(); return ( <main> Welcome to Coding Beauty 😄 <br /> <br /> Route: <b>{pathname}</b> </main> ); }
Displaying the current route in a Next.js app router component

Next.js app router: We need 'use client'

Notice the 'use client' statement at the top.

It’s there because all components in the new app directory are server components by default.

This means we can’t access client-side specific APIs.

We can’t do anything interactive with useEffect or other hooks.

If we try, we’ll get an error.

Because it’s a server environment.

We get an error if we try to use hooks in a server component

Get current route in Next.js getServerSideProps

To get the current route in getServerSideProps, use req.url from the context argument.

src/pages/amazing-url.tsx
import { NextPageContext } from 'next'; import Head from 'next/head'; export function getServerSideProps(context: NextPageContext) { const route = context.req!.url; console.log(`The route is: ${route}`); return { props: { route, }, }; } export default function Home({ route }: { route: string }) { return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.png" /> </Head> <main> Welcome to Coding Beauty 😃 <br /> Route: <b>{route}</b> </main> </> ); }
The current route printed in the console
The current route displayed on the page

Get full URL in Next.js getServerSideProps

To get the current URL in getServerSideProps of a Next.js page, use the getUrl function from the nextjs-current-url library.

src/pages/index.tsx
import { NextPageContext } from 'next'; import Head from 'next/head'; import { getUrl } from 'nextjs-current-url/server'; export function getServerSideProps(context: NextPageContext) { const url = getUrl({ req: context.req }); return { props: { url: url.href, }, }; } export default function Home({ url }: { url: string }) { const urlObj = new URL(url); const { pathname } = urlObj; return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.png" /> </Head> <main> Welcome to Coding Beauty 😃 <br /> <br /> URL: <b>{url}</b> <br /> Route: <b>{pathname}</b> </main> </> ); }
The current URL is displayed on the Next.js page from getServerSideProps()

Get full URL in Next.js component

To get the current URL in a Next.js component, you can use the useUrl hook from the nextjs-current-url library.

With pages directory:

src/pages/index.tsx
import { useUrl } from 'nextjs-current-url'; import Head from 'next/head'; export default function Home() { const { href: currentUrl, pathname } = useUrl() ?? {}; return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Next.js Tutorials by Coding Beauty" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.png" /> </Head> <main> Welcome to Coding Beauty 😄 <br /> <br /> Route: <b>{pathname}</b> URL: <b>{currentUrl}</b> <br /> </main> </> ); }
Displaying the full URL on a React component

useUrl() returns a URL object that gives us more info on the current URL.

Here are some of them:

  • search: the URL’s query parameters. Includes the ?
  • hash: the fragment identifier, the part after the #.
  • href: the complete URL, including the protocol, hostname, port number, path, query parameters, and fragment identifier.
  • protocol: URL’s protocol scheme, like https: or mailto:. Doesn’t include the //.
  • hostname: the URL’s domain name without the port number.
  • pathname: the URL’s path and filename without the query and fragment identifier.
src/pages/amazing-url.tsx
import { NextPageContext } from 'next'; import Head from 'next/head'; import { useUrl } from 'nextjs-current-url'; export default function Home() { const { pathname, href, protocol, hostname, search, hash } = useUrl() ?? {}; return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.png" /> </Head> <main> Welcome to Coding Beauty 😃 <br /> <br /> URL: <b>{href}</b> <br /> Pathname: <b>{pathname}</b> <br /> Protocol: <b>{protocol}</b> <br /> Hostname: <b>{hostname}</b> <br /> Search: <b>{search}</b> <br /> Hash: <b>{hash}</b> </main> </> ); }
Displaying various URL properties on the page

Key takeaways

  • You can use useRouter hook in Next.js to know the current route. It’s like your navigation compass!
  • For getting the current route in a Next.js app router component, usePathname hook from next/navigation is the way to go. But remember, these components are server-side by default.
  • To find out the current route in getServerSideProps, just use req.url from the context. It’s as simple as that!
  • To get the current URL in getServerSideProps, use the getUrl function from nextjs-current-url library. Just pass in the context.req, and you’re good to go!
  • Want to get the full URL? useUrl hook from nextjs-current-url library is your friend. It tells you everything about the URL.

How to Quickly Get the Current URL in Next.js

To get the current URL in a Next.js component, use the useUrl hook from the nextjs-current-url package:

With pages directory:

src/pages/index.tsx
import { useUrl } from 'nextjs-current-url'; import Head from 'next/head'; export default function Home() { const { href: currentUrl, pathname } = useUrl() ?? {}; return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Next.js Tutorials by Coding Beauty" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.png" /> </Head> <main> Welcome to Coding Beauty 😄 <br /> <br /> URL: <b>{currentUrl}</b> <br /> pathname: <b>{pathname}</b> </main> </> ); }
The current URL is displayed on the Next.js page

useUrl() returns a URL object that gives us more info on the current URL.

Get current URL with useState and window.location.href

We can also get the current URL in a client component using useState and window.location.href.

src/pages/index.tsx
import Head from 'next/head'; import { useRouter } from 'next/router'; import { useEffect } from 'react'; export default function Home() { const [currentUrl, setCurrentUrl] = useState<string | null>(null); const { pathname } = useRouter(); useEffect(() => { setCurrentUrl(window.location.href); }, []); return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Next.js Tutorials by Coding Beauty" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.ico" /> </Head> <main> Welcome to Coding Beauty 😄 <br /> <br /> URL: <b>{currentUrl}</b> <br /> pathname: <b>{pathname}</b> </main> </> ); }

The window.location.href property returns a string containing the entire page URL.

We use the useState hook to create state that’ll we store in the current URL.

We set the state in the useEffect hook.

window.location

window.location has other properties that tell you more about the URL. Like:

  • pathname: the path of the URL after the domain name and any optional port number. Query and fragment identifier not included.
  • protocol: URL‘s protocol scheme, like https: or mailto:. Doesn’t include the //.
  • hostname: the URL‘s domain name without the port number.

Here’s a demo where we use some of these properties:

src/pages/index.tsx
import { getUrl } from '@/lib/utils/get-url'; import { NextPageContext } from 'next'; import Head from 'next/head'; import { useEffect, useState } from 'react'; export function getServerSideProps(context: NextPageContext) { return { props: { currentUrl: getUrl({ req: context.req! })?.href, }, }; } export default function Home() { const [myLocation, setMyLocation] = useState<Location | null>(null); useEffect(() => { setMyLocation(window.location); }); return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Next.js Tutorials by Coding Beauty" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.png" /> </Head> <main> You are currently accessing <b>{myLocation?.href}</b> 😃 <br /> Pathname: <b>{myLocation?.pathname}</b> <br /> Protocol: <b>{myLocation?.protocol}</b> <br /> Hostname: <b>{myLocation?.hostname}</b> </main> </> ); }
Displaying various URL segments on the page

We need useEffect to get the current URL

In Next.js, pages render on both the server and client.

So when the server renders the page, there’s no window object available!

Just like in normal Node.js right? Yes – the server environment.

So you’ll get a “window is not defined” error if you try to use window before hydration:

"window is not defined" error in Next.js page

That’s why we use useEffect – to wait till mounting/hydration is done.

Hope that’s clear?

Note: Hydration is when a server-generated web page gets extra client-side features added by the user’s web browser. Features like event listeners, client-side routing, etc.

Get current URL in Next.js app router component

To get the current url in a Next.js app router component, we can also use the useUrl hook from the nextjs-current-url library.

src/app/page.tsx
'use client'; import React from 'react'; import { useUrl } from 'nextjs-current-url'; import { Metadata } from 'next'; export const metadata: Metadata = { title: 'Next.js - Coding Beauty', description: 'Next.js Tutorials by Coding Beauty', }; export default function Page() { const { pathname, href } = useUrl() ?? {}; return ( <main> Welcome to Coding Beauty 😄 <br /> <br /> URL: <b>{href}</b> <br /> route: <b>{pathname}</b> </main> ); }
The current URL is displayed on the Next.js app router component

Next.js app router: We need 'use client'

Notice the 'use client' statement at the top.

It’s there because all components in the new app directory are server components by default.

This means we can’t access client-side specific APIs.

We can’t do anything interactive with useEffect or other hooks, like useUrl.

If we try, we’ll get an error.

Because it’s a server environment.

Get current URL in Next.js getServerSideProps

To get the current URL in getServerSideProps of a Next.js page, use the getUrl function from the nextjs-current-url library.

src/pages/index.tsx
import { NextPageContext } from 'next'; import Head from 'next/head'; import { getUrl } from 'nextjs-current-url/server'; export function getServerSideProps(context: NextPageContext) { const url = getUrl({ req: context.req }); return { props: { url: url.href, }, }; } export default function Home({ url }: { url: string }) { const urlObj = new URL(url); const { pathname } = urlObj; return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.png" /> </Head> <main> Welcome to Coding Beauty 😃 <br /> <br /> URL: <b>{url}</b> <br /> Route: <b>{pathname}</b> </main> </> ); }
The current URL is displayed on the Next.js page from getServerSideProps()

getUrl uses info from context.req object to form the complete current URL.

The URL is not serializable, so we pass href, which is a string.

In the client, we create a URL object again with URL().

We get the pathname with the pathname property.

Let’s check out some more properties of URL:

JavaScript
import { NextPageContext } from 'next'; import Head from 'next/head'; import { getUrl } from 'nextjs-current-url/server'; export function getServerSideProps(context: NextPageContext) { const url = getUrl({ req: context.req }); return { props: { url: url.href, }, }; } export default function Home({ url }: { url: string }) { const urlObj = new URL(url); const { pathname, href, protocol, hostname, search, hash } = urlObj; return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.png" /> </Head> <main> Welcome to Coding Beauty 😃 <br /> <br /> URL: <b>{href}</b> <br /> Pathname: <b>{pathname}</b> <br /> Protocol: <b>{protocol}</b> <br /> Hostname: <b>{hostname}</b> <br /> Search: <b>{search}</b> <br /> Hash: <b>{hash}</b> </main> </> ); }

Here’s what these properties do:

  • href: the complete URL, including the protocol, hostname, port number, path, query parameters, and fragment identifier.
  • protocol: URL’s protocol scheme, like https: or mailto:. Doesn’t include the //.
  • hostname: the URL’s domain name without the port number.
  • pathname: the URL’s path and filename without the query and fragment identifier.
  • search: the URL’s query parameters. Includes the ?
  • hash: the fragment identifier, the part after the #.
Various properties of the URL are displayed on the page.

Note: It’s not possible to get the fragment in getServerSideProps because the browser never sends the part after the # to the server. That’s why there’s no hash here. We’d have to get the current URL in the client-side to access the fragment identifier.

Key takeaways

  • To get the current URL in a Next.js component, we can use useUrl hook from the nextjs-current-url package.
    Or useState and window.location.href in a client component.
  • The window.location has properties like protocol, hostname, and pathname that give more information about the URL.
  • In Next.js pages, use useEffect to wait until mounting/hydration is done to access client-side specific APIs.
  • All components in the new app directory are server components by default.
    To access client-side-specific APIs, set the 'use client' statement at the top.
  • To get the current URL in Next.js getServerSideProps, use getUrl() from the nextjs-current-url package, i.e., getUrl({ req: context.req }).
    The URL is not serializable, so we pass href, which is a string.

How to Fix the “Unknown file extension .ts” Error in ts-node

The “Unknown file extension .ts” error occurs in ts-node occurs when "type": "module" is set in your package.json file. To fix it, run the TypeScript file with ts-node --esm my-file.ts, or remove "type": "module" from your package.json file.

For example, in a project with this package.json file:

package.json
{ "name": "cb-js", "version": "1.0.0", "main": "index.js", "type": "module", "license": "MIT", "devDependencies": { "prettier": "^2.8.1" } }

If you have a TypeScript file in your project, e.g., my-file.ts:

my-file.ts
const num: number = 10; console.log(num ** 2);

Running the ts-node index.ts command will result in the ERR_UNKNOWN_FILE_EXTENSION TypeError in ts-node:

The ERR_UNKNOWN_FILE_EXTENSION TypeError occurs.
The ERR_UNKNOWN_FILE_EXTENSION TypeError occurs.

To fix the “Unknown file extension ‘.ts'” error in ts-node, run ts-node with the --esm option set:

Shell
ts-node --esm my-file.ts # Or ts-node-esm my-file.ts # Or node --loader ts-node/esm my-file.ts
Running ts-node in esm mode.
Running ts-node in esm mode.

To avoid using the --esm flag, add the following to your tsconfig.json file:

tsconfig.json
{ // other settings... "ts-node": { "esm": true, "experimentalSpecifierResolution": "node" } }

After doing this, you’ll be able to run the TypeScript file with only ts-node:

Shell
ts-node my-file.ts
Running the TypeScript file with only ts-node.
Running the TypeScript file with only ts-node.

You may also need to add one or more of the following options to your tsconfig.json file:

tsconfig.json
{ // other settings.. "compilerOptions": { // other compiler options... "esModuleInterop": true, "module": "ESNext", // "module": "CommonJS" should work too "moduleResolution": "Node" }, "include": ["/**/*.ts"], "exclude": ["node_modules"] }

Remove "type": "module" from tsconfig.json file

Alternatively, instead of doing all of the above, you can simply remove the "type": "module" field from your package.json file to fix the ERR_UNKNOWN_FILE_EXTENSION error in ts-node.

tsconfig.json
{ "name": "cb-js", "version": "1.0.0", "main": "index.js", // removed: "type": "module", "license": "MIT", "devDependencies": { "prettier": "^2.8.1" } }

And you’ll be able to run the TypeScript file with ts-node successfully.

Compile TypeScript files into JavaScript

Another way to avoid ERR_UNKNOWN_FILE_EXTENSION is to stop using ts-node altogether. Instead, you can compile your TypeScript files with tsc and run the JavaScript output with node – the classic way.

Shell
# Compile with tsc npx tsc --outDir dist my-file.ts # Run with node node dist/my-file.ts

Basic TypeScript compilation setup

Here’s a great way to set up your project for easily compiling and debugging TypeScript files.

First, install the TypeScript compiler:

Shell
npm i tsc

Then specify the src dir and out dir in tsconfig.json, and enable source maps for seamless Typescript debugging:

tsconfig.json
{ "compilerOptions": { // ... other options "rootDir": "src", // Location of TypeScript files "outDir": "dist", // Location of compiled JavaScript files "sourceMap": true // Generate sourcemaps } }

Finally, create a start NPM script that automatically runs the tsc and node commands one after the other:

JavaScript
{ // ... other options "scripts": { "start": "tsc && node index.js" } }

Now you can run the script easily with npm start.

And you can debug TypeScript in VSCode too.

How to Get an Object Value By Key in TypeScript

You can easily get an object’s value by a key in Typescript using bracket notation, i.e., obj['key'], obj[myVar], etc. If the key exists, you will get the corresponding value back.

For example:

TypeScript
type Car = { name: string; maxSpeed: number; color: string; }; const car: Car = { name: 'CB Flash', maxSpeed: 200, color: 'blue', }; console.log(car['name']); // CB Flash // Dot notation console.log(car.name); // CB Flash // Get value by variable key const prop = 'name'; console.log(car[prop]); // CB Flash // Computed property key const val = car[3 > 1 ? 'name' : 'maxSpeed'] console.log(val) // CB Flash

Dot notation property access

There are two ways to get an object’s value by a property key in TypeScript: dot notation and bracket notation.

In dot notation, we access an object value with the obj.propKey syntax.

TypeScript
type Car = { name: string; maxSpeed: number; color: string; }; const car = { name: 'CB Flash', maxSpeed: 200, color: 'blue', }; console.log(car.name); // CB Flash console.log(car.maxSpeed); // 200 console.log(car.color); // blue

With the obj.propKey syntax, the propKey must be a valid TypeScript identifier. Otherwise, a syntax error will be thrown:

TypeScript
type Car = { [propKey: string]: string }; const car: Car = {}; car.100 = 'go faster'; // ❌ SyntaxError console.log(car.100); // ❌ SyntaxError

propKey can also be a reserved keyword, like let, var, async, etc.

TypeScript
type Car = { [propKey: string]: string }; const car: Car = {}; car.let = 'works'; car.await = 'works too'; console.log(car.let); // works console.log(car.await); // works too

Bracket notation property access

In bracket notation, we access the property value with the obj[expression] syntax. The expression should evaluate to a string or Symbol that represent the property’s key.

TypeScript
type Car = { name: string; maxSpeed: number; color: string; }; const car: Car = { name: 'CB Flash', maxSpeed: 200, color: 'blue', }; console.log(car['name']); // CB Flash console.log(car['maxSpeed']); // 200 console.log(car['color']); // blue

Unlike dot notation, with bracket notation, we can access keys that are not valid TypeScript identifiers, like numbers and keys containing spaces.

TypeScript
type Car = { [propKey: string]: string }; const car: Car = {}; car['100'] = 'go faster'; car['year produced'] = 2022; console.log(car['100']); // go faster console.log(car['year produced']); // 2022

Computed property names

The expression we put in-between the brackets can be as complex as possible, as long it evaluates to a string or Symbol.

For example, we can put a ternary expression in-between the brackets:

TypeScript
type Car = { name: string; maxSpeed: number; color: string; }; const car: Car = { name: 'CB Flash', maxSpeed: 200, color: 'blue', }; const num = 3; const val = car[num > 1 ? 'name' : 'maxSpeed']; console.log(val); // CB Flash

Note: If the expression to the left of the ? is truthy, the ternary operator returns the value to the left. Otherwise, it returns the value to the right.

The ternary expression evaluates to the 'name' key, so the corresponding property value is returned.

You can also this computed property names approach to set a new property on a object.

TypeScript
type Car = { [propKey: string]: string | number; }; const car: Car = {}; const num = 7; car[num > 10 ? 'name' : 'maxSpeed'] = 500; console.log(car['name']); // undefined console.log(car['maxSpeed']); // 500

How to Fix the “Cannot find name ‘console'” Error in TypeScript

The “cannot find name ‘console'” error occurs when you try to access the global console object in a TypeScript file. To fix it, install the @types/node NPM package for Node.js environments, or add 'DOM' to the lib array in your tsconfig.json for browser environments.

The "cannot find name 'console'" TypeScript error occuring in VSCode.
The “cannot find name ‘console'” TypeScript error occuring in VSCode.
index.ts
/* * Cannot find name 'console'. Do you need to change your * target library? Try changing the 'lib' compiler option * to include 'dom'.ts(2584) */ console.log('coding beauty');

Install Node.js typings

If your code is running in a Node.js environment, you can fix the “cannot find name ‘console'” error by running the following command at the root of your project directory.

Shell
npm i -D @types/node # Yarn yarn add --dev @types/node

This should resolve the error for Node.js runtimes.

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.

Including 'node' string in the tsconfig.json types array will make the Node.js typings visible to the TypeScript compiler.

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

Add 'DOM' to lib array in tsconfig.json file

If your code is running in a browser, trying adding a 'DOM' string to the lib array in your tsconfig.json file.

tsconfig.json
{ "compilerOptions": { "lib": [ // other libs... "ES6", "DOM" ], // other settings... }, }

Doing this tells TypeScript that your code is client-side code, and it should provide a set of type definitions for built-in JavaScript APIs found in browser environments.

Restart code editor

If the error persists after trying out all these solutions, restarting your IDE or code editor might help.

Conclusion

To fix the “cannot find name ‘console’ error” in TypeScript, install Node typings if your code runs in Node.js, or add the 'DOM' string to your types array in your tsconfig.json if running in a browser.

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 Fix the “Cannot redeclare block-scoped variable” Error in TypeScript

Are you experiencing the “Cannot redeclare block-scoped variable” error in TypeScript? This error can occur for two reasons:

  1. Using variable names that clash with TypeScript global typings.
  2. Redeclaring a variable in the same block scope.
The "cannot redeclare block-scoped variable" TypeScript error occuring in VS Code.
The “cannot redeclare block-scoped variable” error occurring in VS Code.

We’ll look at solutions for these possible causes in this article.

Fix for: using variable names that clash with TypeScript global typings

The “Cannot redeclare block-scoped variable” error occurs if you declare a variable with a name that clashes with one declared in TypeScript global typings.

index.ts

// ❌ Cannot re-declare block-scoped variable "name".
const name = 'Coding Beauty';

console.log(name);

To fix the error in this case, convert your file to an ES module, like this:

index.ts

// ✅ variable declared successfully
const name = 'Coding Beauty';

console.log(name); // Coding Beauty

export {};

The export {} statement indicates that the file is an ES module. In TypeScript, any file containing a top-level import or export is considered to be a module.

Without top-level import or export declarations, the file gets treated as a script whose contents are available in the global scope (and to other modules). This is what causes the name clash between our name variable and the name variable declared in TypeScript global typings.

Another way to fix this is to use another name to declare the variable that does not clash with the global typings.

index.ts

// ✅ variable declared successfully
const theName = 'Coding Beauty';

console.log(theName); // Coding Beauty

export {};

Fix for: redeclaring a variable in the same block scope

The “cannot redeclare block-scoped variable” error will also occur if you try to declare a variable using a name previously used in the same block scope.

const language = 'JavaScript';

// ❌ Cannot redeclare block-scoped variable 'language'.
const language = 'PHP';

You can easily fix the error in the case by using a different name for the new variable.

const language = 'JavaScript';

// ✅ variable declared successfully
const language2 = 'PHP';

If you intended to assign a new value to the variable, the proper way to do this is to declare the variable with the let keyword, and change its value without redeclaring it.

// declare with "let" keyword
let language = 'JavaScript';

// reassign without redeclaring
language = 'PHP';

console.log(language); // PHP

Note

Unlike const or let, the var keyword doesn’t complain about redeclared variables.

var language = 'JavaScript';

// No error thrown
var language = 'PHP';

Redeclaring variables can cause tricky bugs in your code, and this is one reason to avoid using the var keyword.

You can declare a variable with the same name in a nested block. The variable in the nested block is separate from the one declared in the outer scope.

let color = 'red';

if (true) {
  let color = 'yellow';

  console.log(color); // yellow
}

console.log(color); // red

Note

If you use var keyword to do this, it will override the value of the variable in the outer scope.

var color = 'red';

if (true) {
  var color = 'yellow';

  console.log(color); // yellow
}

console.log(color); // yellow

Another reason to avoid using var.

It doesn’t have to be an if block, we can do this in any nested block designated with curly braces ({ and }).

let color = 'red';

{
  let color = 'yellow';

  console.log(color); // yellow
}

console.log(color); // red

Fix: use an IIFE

Another way to fix the error is to wrap the code containing the variable with an immediately invoked function expression (IIFE). IIFEs are functions that run as soon as they are defined, and they can help to avoid name clashes that cause this error.

const fruit = 'Apple';

(() => {
  const fruit = 'Banana';

  // ✅ variable declared successfully
  console.log(fruit); // Banana
})();

console.log(fruit); // Apple

This fix also solves the issue of TypeScript global typing clashes we looked at earlier.

index.ts

(() => {
  const name = 'Coding Beauty';

  console.log(name); // Coding Beauty
})();

How to Fix the Cannot Find Name ‘it’ Jest Error in TypeScript

To fix the “cannot find name ‘it'” Jest error, install the type definitions for Jest with npm i -D @types/jest and add them to the types array in your tsconfig.json file.

This error occurs when you try to use the it() function from Jest in a TypeScript file, but TypeScript cannot find the type definitions for the package.

Here is an example of the error occurring in Visual Studio Code:

The "cannot find name it" Jest error occurring in Visual Studio 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 Jest by running the following command in a terminal at the root directory of your project:

npm i -D @types/jest

If you didn’t already have Jest installed, you can install it with the type definitions in one command:

npm i -D @types/jest jest

Add typings to tsconfig.json types array

In some cases, this is all you need to do and the error will stop. But if it persists, you’ll need to add jest to the types array in your tsconfig.json file, so it looks something like this:

tsconfig.json

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

Include test files

If the error still doesn’t go away, ensure that TypeScript does not ignore the directory containing your test files. If you’ve set the include array in your tsconfig.json file, ensure the patterns specified in this array match the directory where your test files are located.

For example, if your tests 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 test files with a specific ending or extension. For example, we can include all files ending with “.spec.ts” and “.test.ts” with the following configuration:

tsconfig.json

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

Fix the Cannot Find Name ‘require’ Error in TypeScript

To fix the “cannot find name ‘require'” error in TypeScript, install the @types/node package into your project by running npm i -D @types/node.

This error can occur when you try to use the Node.js require() function in a TypeScript file.

The "cannot find name 'require' error in TypeScript.

You can fix it by running the following command in a terminal window at the root directory of your project:

npm i -D @types/node

If the error persists, try adding "node" to the types array in your tsconfig.json file:

tsconfig.json

{
  "compilerOptions": {
    "types": [
      // ... other types
      "node"
    ],
  },
}

Tip

If you’re just doing simple testing, you can quickly resolve this error by defining a require variable at the top of the TypeScript file:

declare var require: any;