microsoft / microsoft/TypeScript

Inconsistent typechecking with require() in JS and TS

Abierto
#60,032 5 comentarios 1 reacción 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Has Repro Needs More Info
Lenguaje dominante
Go
Estrellas
111k
Forks
14.4k
Merge medio
1 d 19 h
PR fusionados (30 d)
117

Descripción

🔎 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

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza con el Workbench Repro proporcionado y compara las formas require() e import en los archivos de módulo CommonJS y ESM .js y .ts indicados. Sigue los puntos de entrada de comprobación de tipos y resolución de módulos para estos casos y, después, añade cobertura de regresión que muestre una comprobación coherente de propiedades y las importaciones CommonJS de .ts en toda la matriz.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
javascript, node.js, typescript
Área
compilers
Tipo de issue
Error
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
30/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.