镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

allow voluntary .ts suffix for import paths #37582

Description

Search Terms

.ts
suffix
imports
extension

Suggestion

Typescript doesn't recognize file imports with .ts suffix.
Allow voluntary .ts to be added to import paths.

Use Cases

It seems right to be able to use a correct path to a file without magic resolution.
This would help to align with deno which uses mandatory suffixes o files.

Examples

let
import a from "path/to/a.ts"
behave the same as
import a from "path/to/a"

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

Activity

  1. timreichen commented on Jun 3, 2020

    @timreichen
    Author

    After some more research I wonder if that behavior could even be more guided by a compiler option like --noImplicitSuffix.
    That would be in alignment with --noImplicitAny and give the developer the choice, yet push for a valid, not "magical" resolved path if not set.

    What are your thoughts on that?

  2. Jack-Works commented on Aug 12, 2020

    @Jack-Works
    Contributor
  3. zacnomore commented on Aug 14, 2020

    @zacnomore

    #35148

    Read through the above and it seems to boil down to multiple build targets with different file extensions throws a wrench in things when supporting using the file extensions on imports. Where it diverges in my mind, and hopefully Jack Works (@Jack-Works) you can illuminate this a bit, is that we'd be importing .ts extensions which would have to be rewritten anyways.

  4. resynth1943 commented on Dec 12, 2020

    @resynth1943

    So... where are we actually at with this?

    Scattered issues / feature requests don't help, and the confusing (and somewhat untimely) response(s) from official TypeScript members haven't helped me understand how this feature will be implemented (it will have to be, eventually).

    All I can ascertain is that this is has yet to be resolved.

    Can someone explain in plain English when and how these multiple issues will be fixed, please?

  5. 107 remaining items

  6. vixalien commented on Dec 13, 2022

    @vixalien

    I hope this also allows enforcing the use of extensions as an option so that imports without extensions aren't allowed

  7. andrewbranch commented on Dec 14, 2022

    @andrewbranch
    Member

    It does not. You might want to track #50153, and if you’re concerned with Deno, see my advice at #51669 (comment).

  8. karlhorky commented on Dec 14, 2022

    @karlhorky
    Contributor

    enforcing the use of extensions as an option so that imports without extensions aren't allowed

    To approach this problem from another angle, you may want to consider eslint-plugin-node with the node/file-extension-in-import option:

    https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/file-extension-in-import.md

    This is what we've been using to enforce .js extensions in our TypeScript code (because we're using ESM with Node.js, which requires the extensions). Haven't tried it yet with .ts extensions.

  9. andrewbranch commented on Dec 14, 2022

    @andrewbranch
    Member

    If you are compiling TS code to JS code that will run in Node, you should be using --module nodenext (which implies --moduleResolution nodenext), which requires extensions in precisely the places that Node does. No lint rule should be necessary if your reason for enforcing extensions is that you want your code to run in Node. That is built into TypeScript, and has been for about a year. #51669 is made for bundlers, and there is not a single bundler I know of (and I tested a bunch) that ever requires extensions on imports, so likewise it is not a requirement of the module resolution mode.

  10. ctjlewis commented on Dec 14, 2022

    @ctjlewis
    Contributor

    Just saw #51669–is this really finally fixed?!

  11. karlhorky commented on Dec 15, 2022

    @karlhorky
    Contributor

    No lint rule should be necessary if your reason for enforcing extensions is that you want your code to run in Node. That is built into TypeScript, and has been for about a year.

    We added this lint rule because we had breakages that we would only see in the production builds (because use tsm and esbuild for dev mode, which does not have a problem with lacking extensions).

    The inconsistencies between bundlers allowing no extensions and .ts extensions and TypeScript allowing for module resolution to other file extensions like .tsx have been a bit of a headache to say the least, lots of hours spent on this in the ecosystem:

    Ideal feels like TS should just allow for .ts / .tsx / etc extensions as well and just transpile those import paths to whatever the final file extension will be, as an exception of the rule "TypeScript doesn't modify JavaScript code you write"

    It seems almost like maybe that's what --moduleResolution bundler + allowImportingTsExtensions is? But it doesn't seem to be able to emit like this, which would also be desirable.

  12. karlhorky commented on Dec 15, 2022

    @karlhorky
    Contributor

    But indeed, TypeScript does show the error about missing file extensions also in the IDE, which is great - thanks for the tip! I needed to do some configuration for this, but it's working.

    I'll try applying it to those projects, maybe they are just not configured the same way.

    Screenshot 2022-12-15 at 10 24 26

    I needed to add "type": "module" to my package.json as well as a few things to my tsconfig.json:

    {
      "$schema": "https://json.schemastore.org/tsconfig",
      "compilerOptions": {
        "lib": ["dom", "dom.iterable", "esnext"],
        "module": "NodeNext",
        "target": "ESNext",
        "moduleResolution": "NodeNext",
        "resolveJsonModule": true,
        "esModuleInterop": true,
        "isolatedModules": true,
        "allowJs": true,
        "downlevelIteration": true,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "noFallthroughCasesInSwitch": true,
        "skipLibCheck": true,
        "strict": true,
        "incremental": true,
        "noUncheckedIndexedAccess": true
      },
      "include": [
        "**/.eslintrc.cjs",
        "next-env.d.ts",
        "**/*.ts",
        "**/*.tsx",
        "**/*.cjs",
        "**/*.mjs"
      ],
      "exclude": ["node_modules", "build"]
    }
  13. andrewbranch commented on Dec 15, 2022

    @andrewbranch
    Member

    I needed to add "type": "module" to my package.json

    Yes, because without either this or .mts/.mjs extensions, you do not have ES modules at all. Node supports both ESM and CJS files, and CJS files are allowed to write module specifiers without extensions. All your .ts files are CJS modules until you add "type": "module". (There will also be a new flag in 5.0 that prevents you from writing ESM syntax in CJS modules, since that is probably a major source of confusion: #51479.)

    as well as a few things to my tsconfig.json

    This rule is only relevant in node16/nodenext because that’s the only mode that targets versions of Node that have ESM support. The mode called node is out of date and is being renamed to node10: #51901.

  14. ljharb commented on Dec 15, 2022

    @ljharb
    Contributor

    Andrew Branch (@andrewbranch) it would be really great if TS made it easy to use native ESM without type module, since that package.json flag causes lots of issues with outdated tooling and also causes lots of confusion for new users.

  15. andrewbranch commented on Dec 15, 2022

    @andrewbranch
    Member

    Jordan Harband (@ljharb) can you expound on that? In modes made for Node, we’re just doing what Node requires (assuming it’s invoked with no special CLI flags altering the behavior) as far as I know. If we were to emit a .js file with ESM syntax, users would get this:

    image

    image text
    // a.js
    import path from "path";
    
    ❯ node --version
    v16.17.1
                                                                                                                                         
    ❯ node a.js
    (node:8214) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
    (Use `node --trace-warnings ...` to show where the warning was created)
    /Users/andrew/Developer/microsoft/eg/js/a.js:1
    import path from "path";
    ^^^^^^
    
    SyntaxError: Cannot use import statement outside a module
        at Object.compileFunction (node:vm:360:18)
        at wrapSafe (node:internal/modules/cjs/loader:1055:15)
        at Module._compile (node:internal/modules/cjs/loader:1090:27)
        at Object.Module._extensions..js (node:internal/modules/cjs/loader:1180:10)
        at Module.load (node:internal/modules/cjs/loader:1004:32)
        at Function.Module._load (node:internal/modules/cjs/loader:839:12)
        at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
        at node:internal/main/run_main_module:17:47
    
  16. ljharb commented on Dec 15, 2022

    @ljharb
    Contributor

    Andrew Branch (@andrewbranch) right - i'm asking for there to be a way to emit .mjs files instead (or .cjs, if it's CJS, i suppose).

  17. andrewbranch commented on Dec 15, 2022

    @andrewbranch
    Member

    There is, just name your files .mts or .cts

  18. ljharb commented on Dec 15, 2022

    @ljharb
    Contributor

    ah, ok great thanks :-)

  19. jeremyjacob commented on Jan 14, 2023

    @jeremyjacob

    See the following tsconfig.json:

    {
        "compilerOptions": {
             "moduleResolution": "bundler",
             "allowImportingTsExtensions": true
        }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Fix AvailableA PR has been opened for this issueSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions