The “Unexpected reserved word ‘enum'” syntax error happens in JavaScript happens because enum is not a valid keyword in JavaScript, but it is reserved.
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!
JavaScriptCopied!
// ❌ 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:
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.
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.tsxCopied!
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>
</>
);
}
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:
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.
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 #.
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.
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:
After doing this, you’ll be able to run the TypeScript file with only ts-node:
ShellCopied!
ts-node my-file.ts
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.jsonCopied!
{
// 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.
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.
ShellCopied!
# 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:
ShellCopied!
npm i tsc
Then specify the src dir and out dir in tsconfig.json, and enable source maps for seamless Typescript debugging:
tsconfig.jsonCopied!
{
"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:
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:
TypeScriptCopied!
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.
TypeScriptCopied!
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:
TypeScriptCopied!
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.
TypeScriptCopied!
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.
TypeScriptCopied!
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.
TypeScriptCopied!
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:
TypeScriptCopied!
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.
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.
index.tsCopied!
/*
* 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.
ShellCopied!
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.jsontypes array will make the Node.js typings visible to the TypeScript compiler.
tsconfig.jsonCopied!
{
"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.jsonCopied!
{
"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.
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.
index.tsCopied!
/* 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.
ShellCopied!
# 👇 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:
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:
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.
By Tari Ibaba
/ Last updated on September 29, 2022
Are you experiencing the “Cannot redeclare block-scoped variable” error in TypeScript? This error can occur for two reasons:
Using variable names that clash with TypeScript global typings.
Redeclaring a variable in the same block scope.
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.
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.
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.
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.
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:
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.jsontypes 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:
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:
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: