microsoft / microsoft/TypeScript

Inconsistent typechecking with require() in JS and TS

Ouverte
#60,032 5 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Has Repro Needs More Info
Langage dominant
Go
Étoiles
111k
Forks
14.4k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

Description

🔎 Search Terms

require import js ts module esm esmodule cjs commonjs

🕗 Version & Regression Information
  • This happens in the nightly version of TS
⏯ Playground Link

Multiple files not supported in playground, see bug workbench

💻 Code
// @types: ["node"]
// @allowJs
// @checkJs

// @filename: module-cjs-js.js
const Value = "module-cjs-js";
module.exports = { Value };

// @filename: module-cjs-ts.ts
const Value = "module-cjs-ts";
module.exports = { Value };

// @filename: module-esm-js.js
const Value = "module-esm-js";
export { Value };

// @filename: module-esm-ts.ts
const Value = "module-esm-ts";
export { Value };

// @filename: main-js.js
const ConstRequireCjsJs = require("./module-cjs-js");
const ConstRequireEsmJs = require("./module-esm-js");
const ConstRequireCjsTs = require("./module-cjs-ts");
const ConstRequireEsmTs = require("./module-esm-ts");
console.log(ConstRequireCjsJs.Value); // (alias) const Value: "module-cjs-js"
//                            ^?
console.log(ConstRequireEsmJs.Value); // (alias) const Value: "module-esm-js"
//                            ^?
console.log(ConstRequireCjsTs.Value); // Error: Property 'Value' does not exist on type 'typeof import("./module-cjs-ts")'
//                            ^?
console.log(ConstRequireEsmTs.Value); // (alias) const Value: "module-esm-ts"
//                            ^?

import * as ImportFromCjsJs from "./module-cjs-js";
import * as ImportFromEsmJs from "./module-esm-js";
import * as ImportFromCjsTs from "./module-cjs-ts";
import * as ImportFromEsmTs from "./module-esm-ts";
console.log(ImportFromCjsJs.Value); // (alias) const Value: "module-cjs-js"
//                          ^?
console.log(ImportFromEsmJs.Value); // (alias) const Value: "module-esm-js"
//                          ^?
console.log(ImportFromCjsTs.Value); // Error: Property 'Value' does not exist on type 'typeof import("./module-cjs-ts")'
//                          ^?
console.log(ImportFromEsmTs.Value); // (alias) const Value: "module-esm-ts"
//                          ^?

// @filename: main-ts.ts
const ConstRequireCjsJs = require("./module-cjs-js");
const ConstRequireEsmJs = require("./module-esm-js");
const ConstRequireCjsTs = require("./module-cjs-ts");
const ConstRequireEsmTs = require("./module-esm-ts");
console.log(ConstRequireCjsJs.Value); // any
//                            ^?
console.log(ConstRequireEsmJs.Value); // any
//                            ^?
console.log(ConstRequireCjsTs.Value); // any
//                            ^?
console.log(ConstRequireEsmTs.Value); // any
//                            ^?

import * as ImportFromCjsJs from "./module-cjs-js";
import * as ImportFromEsmJs from "./module-esm-js";
import * as ImportFromCjsTs from "./module-cjs-ts";
import * as ImportFromEsmTs from "./module-esm-ts";
console.log(ImportFromCjsJs.Value); // (alias) const Value: "module-cjs-js"
//                          ^?
console.log(ImportFromEsmJs.Value); // (alias) const Value: "module-esm-js"
//                          ^?
console.log(ImportFromCjsTs.Value); // Error: Property 'Value' does not exist on type 'typeof import("./module-cjs-ts")'
//                          ^?
console.log(ImportFromEsmTs.Value); // (alias) const Value: "module-esm-ts"
//                          ^?

import ImportRequireCjsJs = require("./module-cjs-js");
import ImportRequireEsmJs = require("./module-esm-js");
import ImportRequireCjsTs = require("./module-cjs-ts");
import ImportRequireEsmTs = require("./module-esm-ts");
console.log(ImportRequireCjsJs.Value); // (alias) const Value: "module-cjs-js"
//                             ^?
console.log(ImportRequireEsmJs.Value); // (alias) const Value: "module-esm-js"
//                             ^?
console.log(ImportRequireCjsTs.Value); // Error: Property 'Value' does not exist on type 'typeof import("./module-cjs-ts")'
//                             ^?
console.log(ImportRequireEsmTs.Value); // (alias) const Value: "module-esm-ts"
//                             ^?

Workbench Repro

🙁 Actual behavior

Type resolution is inconsistent when using require() from .js and .ts files:

  • CommonJS modules with .ts extension have no properties regardless of import type (no error if ESModule.ts or CommonJS.js)
  • Using require() in a .ts file is always unchecked (checked in a .js file or in .ts file with import X = syntax)
MainExt Type Ext RequireOrImport Issue
JS CJS JS const X = require("Y")
JS ESM JS const X = require("Y")
JS CJS TS const X = require("Y") Error
JS ESM TS const X = require("Y")
JS CJS JS import * as X from "Y"
JS ESM JS import * as X from "Y"
JS CJS TS import * as X from "Y" Error
JS ESM TS import * as X from "Y"
JS CJS JS const X = require("Y")
JS ESM JS const X = require("Y")
JS CJS TS const X = require("Y") Error
JS ESM TS const X = require("Y")
TS CJS JS const X = require("Y") Any
TS ESM JS const X = require("Y") Any
TS CJS TS const X = require("Y") Any
TS ESM TS const X = require("Y") Any
TS CJS JS import * as X from "Y"
TS ESM JS import * as X from "Y"
TS CJS TS import * as X from "Y" Error
TS ESM TS import * as X from "Y"
TS CJS JS import X = require("Y")
TS ESM JS import X = require("Y")
TS CJS TS import X = require("Y") Error
TS ESM TS import X = require("Y")
🙂 Expected behavior

I expected require() to be typechecked in .ts files because it's typechecked in .js files.
I expected imports of CommonJS .ts files to work because CommonJS .js files work and are typechecked.

Additional information about the issue

This problem happens when porting an existing Node.JS codebase that uses CommonJS require() modules to TypeScript. It's not possible to port the code without also forcing it into ES Modules because:

  • CommonJS .ts files don't work
  • require() from .ts files is not typechecked

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par le Workbench Repro fourni et comparez les formes require() et import dans les fichiers de modules CommonJS et ESM .js et .ts indiqués. Suivez les points d’entrée de la vérification des types et de la résolution des modules pour ces cas, puis ajoutez une couverture de régression montrant une vérification cohérente des propriétés et des imports CommonJS .ts dans toute la matrice.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
javascript, node.js, typescript
Domaine
compilers
Type d'issue
Bug
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
30/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.