pass "no-var-requires" ESLint rule with an import of a module without declaration file

Viewed 527

Within my NodeJS/TypeScript project, I'm using fluent-ffmpeg and it works fine. In order to use it, I need to import path properties of both ffmpeg-installer/ffmpeg and ffprobe-installer/ffprobe.

ffmpeg import looks like:

import * as ffmpegInstaller from "@ffmpeg-installer/ffmpeg";

It made possible by the existence of a declaration file index.d.ts under @ffmpeg-installer/ffmpeg module's types folder.

Regarding ffprobe it's not possible, due to the lack of a declaration file like the one mentioned above. When trying: import * as ffprobeInstaller from "@ffprobe-installer/ffprobe"; an error shows up:

Could not find a declaration file for module '@ffprobe-installer/ffprobe'. '<...>/node_modules/@ffprobe-installer/ffprobe/index.js' implicitly has an 'any' type. Try npm i --save-dev @types/ffprobe-installer__ffprobe if it exists or add a new declaration (.d.ts) file containing declare module '@ffprobe-installer/ffprobe';ts(7016)

Neither npm i --save-dev @types/ffprobe-installer__ffprobe gives a thing.

So I use const ffprobeInstaller = require("@ffprobe-installer/ffprobe"); instead, and it works.

However, here comes ESLint and complains:

Require statement not part of import statement. eslint (@typescript-eslint/no-var-requires)

So I tried to replace it with: import ffprobeInstaller = require("@ffprobe-installer/ffprobe"); as suggested in ESLint documentation but then i'm getting the Could not find a declaration file...ts(7016) again.

There are some directions I can take to overcome the issue:

  • Creating my own declaration file
  • disable no-var-requires rules or ignore it locally

My question is: How can I pass ESLint's no-var-requires rule without creating a declaration file nor disabling the rule.

2 Answers

Think your problem from 2 sides,

  1. How to pass typescript -> Of course you need a declaration file, by either writing your own file or installing an existed package
  2. How to pass eslint -> Use an import statement instead of var-requires.

The interesting thing is that require has any return type. That's why you thought you have solved the typescript part. But in fact, this built-in type acts like a quick declaration file, and will lose type restrictions.

interface NodeRequireFunction {
    (id: string): any;
}

In summary, creating the declaration is required, no matter it is a file or from somewhere implicitly. And eslint is just something introduced by accident.

@ffprobe-installer/ffprobe is a pure javascript package with no types available for it. If you just want to use it and treat everything from it as an any then you can do what the compiler suggested and create a new declaration file. It only needs to contain the line

declare module '@ffprobe-installer/ffprobe'

For example create a file called ffprobe.d.ts in the root of your source code, add the line above and the compile error will go away.

If you want to by-pass the compiler error by using require instead of import then you have to disable the lint rule with eslint-disable-next-line or similar. There is no way to stop eslint complaining abut using require without disabling the rule somewhere because the rule is doing what it is meant to be doing.

Related