typescript

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:

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.

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.

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 occurs when you try to use the describe() function in a TypeScript file, but TypeScript cannot find the type definitions for the package.

The "cannot find name 'describe'" error occuring 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.

# 👇 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
  }
}

Similarly, if you’re using Mocha, 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, ensure that TypeScript is not ignoring 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 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 the following configuration:

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);
  });
});

Similarly, if we’re 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;

[SOLVED] An Implementation Cannot Be Declared in Ambient Contexts Error in TypeScript

Are you experiencing the “an implementation cannot be declared in ambient contexts” error in TypeScript? This error can occur when you try to include logic in declaration files, for example:

car.d.ts

declare module 'car' {
  export class Car {
    color: string;
    maxSpeed: number;
    started: boolean;

    // Error: An implementation cannot be declared in ambient contexts
    start() {
      this.started = true;
    }
  }
}

Ambient declarations only exist in the type system and are erased at runtime, so they are not meant to contain implementations. The car module declaration in the example above is only meant to specify type information for a car module that is implemented somewhere else.

To fix this error, remove the implementation:

car.d.ts

declare module 'car' {
  export class Car {
    color: string;
    maxSpeed: number;
    started: boolean;

    start(); // implementation removed
  }
}

How to Fix the Cannot Use Namespace as a Type Error in TypeScript

Are you experiencing the “cannot use namespace as a type” error in TypeScript?

This error can occur when you try to import types declared as a module. For example:

car.d.ts

declare module 'car' {
  class Car {
    color: string;
    age: number;
    maxSpeed: number;
  }
}

index.ts


import Car from 'car';

// Cannot use namespace 'Car' as a type.
const user: Car = {
  color: 'red',
  age: 2,
  maxSpeed: 120,
};

To fix this error, use an export assignment to specify a default export for the namespace, like this:

car.d.ts

declare module 'car' {
  class Car {
    color: string;
    age: number;
    maxSpeed: number;
  }
  export = Car;
}