Skip to content

Infer ESM-compatible module setting for inferred projects in "type": "module" or .mjs/.mts files #46698

Description

If you open a directory in VS Code with no tsconfig.json and start writing an .mjs file, you get an error that you can’t use import.meta, which is obviously wrong and super annoying, and if you don’t want to add a tsconfig, there’s no way to fix this other than ts-ignoreing it.

The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node12', or 'nodenext'.ts(1343)

The same goes for writing a .js or .ts file covered by a package.json that has "type": "module".

Activity

  1. andrewbranch commented on Feb 3, 2022

    @andrewbranch
    MemberAuthor

    I started writing some stuff to infer the module kind for inferred projects, but what would be the downside of having VS Code simply change its default for inferred projects to esnext? Daniel Rosenwasser (@DanielRosenwasser) Wesley Wigham (@weswigham) thoughts?

  2. DanielRosenwasser commented on Feb 3, 2022

    @DanielRosenwasser
    Member

    I think that would be fine - but it might make sense to also bump up the target to es2020 now.

  3. DanielRosenwasser commented on Feb 3, 2022

    @DanielRosenwasser
    Member

    Matt Bierner (@mjbvz), what are your thoughts on doing the following for inferred projects?

    • set the module to esnext
    • set the target option to es2020
  4. mjbvz commented on Feb 3, 2022

    @mjbvz

    Not sure, what would be the impact of changing the module? The current default is commonjs

    I think our target already defaults to es2020: https://github.com/microsoft/vscode/blob/e794a5444b93b08092167a206c69ad56f7a1d358/extensions/typescript-language-features/src/utils/tsconfig.ts#L31

  5. weswigham commented on Feb 3, 2022

    @weswigham
    Member

    Assuming you also set moduleResolution: node to make up for un-setting module: commonjs so you still get package specifier resolution, module: esnext is going to be a little wonky for TS files; it does things like disallow import a = require("b") and export = expr, while in exchange you allow import.meta. The (upcoming) nodenext behaviors (where import a = require("b") is always defined and allowed and export = expr is at least allowed in cjs targeting contexts) would be more broadly applicable, imo (and likewise allow import.meta in known-module contexts). Both would start allowing top-level await (in certain contexts), which is... maybe stable enough? It ships without flags in major runtimes, at least.

    The current default, commonjs, is definitely our most stable default for modules, to be sure. It's probably also still the most broadly applicable for a random sample of files. I dunno, it's in some ways weird to have a "default" module system nowadays, when we live in a fracturing module ecosystem, where commonjs is being slowly drained of life by people separately trying browser native esm flavors, webpack and co esm flavors, deno esm flavors, and node native esm flavors. Still, I think cjs currently reigns supreme above them all in actual usage, so unless you wanted to be a trend-setter, I'm unsure if swapping the default module would actually improve the experience for most people (and not just users on the cutting edge).

  6. andrewbranch commented on Feb 3, 2022

    @andrewbranch
    MemberAuthor

    When we’re talking about inferred projects, I think it makes sense to be as permissive as possible. module primarily impacts emit, and I don’t think it makes sense to think about emit without any configuration. I think disallowing ImportEquals and ExportEquals won’t be a problem for user code, but it might be a little annoying when you’re navigating into random node_modules .d.ts files, which use those syntaxes a lot more than non-ambient code. I do think node12 or nodenext would possibly be a better selection, but we need to wait until those are shipped and stable (and this issue can wait on that if needed).

  7. jimmywarting commented on Feb 19, 2022

    @jimmywarting
    Contributor

    Can you just look at a file and detect if it use import or require() export default fn vs exports = fn

    no package.json, tsconfig.json or jsconfig.json or vscode settings would be the best.

  8. andrewbranch commented on Mar 1, 2022

    @andrewbranch
    MemberAuthor

    it does things like disallow import a = require("b") and export = expr

    I think disallowing ImportEquals and ExportEquals won’t be a problem for user code, but it might be a little annoying when you’re navigating into random node_modules .d.ts files, which use those syntaxes a lot more than non-ambient code

    Oh wait, those are only errors in non-ambient code anyway. On second thought I think es2020 or esnext is a perfectly reasonable default.

  9. andrewbranch commented on Mar 9, 2022

    @andrewbranch
    MemberAuthor

    We decided to try (via Matt Bierner (@mjbvz)) setting module to esnext and moduleResolution to node in an upcoming VS Code Insiders.

  10. mjbvz commented on Mar 9, 2022

    @mjbvz

    I've update VS Code to use module: esnext for implicit projects by default

  11. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScript

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions