TypeScript: Suppressing "The import path cannot end with a '.ts' extension" error?

From @hooper-hc on September 30, 2018 8:45

when i use

import { PI } from './module.1.ts'

import an module .

vscode linter notice me an error

‘The import path cannot end with a “.ts” extension. Consider changing to import “./module.1”。’

hao can i hidden the notice ?

Copied from original issue: Microsoft/vscode#59690

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 119
  • Comments: 105 (15 by maintainers)

Commits related to this issue

Most upvoted comments

This issue has been marked as ‘Question’ and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you’re still waiting on a response, questions are usually better suited to stackoverflow.

Suppose you have two files: a.ts: import * as b from "./b.ts"; b.ts: export const b: number = 0;

When we compile a.ts, we don’t change import specifiers. So the output a.js will contain the same import specifier “./b.ts”, although possibly translated to require("./b.ts"). Then when you try to run a.js it will fail, because there will be no b.ts to import from, only b.js. (Or without --outDir where b.js is next to b.ts, it will resolve the import to b.ts, then fail parsing at : number.)

Instead, you should omit the file extension from your imports, or use the .js extension.

no,I use deno exec the file 。 without compile。

I’m using deno as well. I found that commenting // @ts-ignore each line of an import works.

// @ts-ignore
import coerceToArray from './journey.coerce-to-array.ts'
// @ts-ignore
import fnFree from './journey.fn-free.ts'
// @ts-ignore
import fnReduce from './journey.fn-reduce.ts'

Is there anyway to shut this requirement off globally in ts-config?

I also tried @zhmushan’s solution and It didn’t fix the issue 😦

This is closed, but it’s not fixed.

Adding my vote here for support for Deno. The current behavior results in TypeScript resolving all types imported in this way to any, which makes developing software for Deno rather difficult.

In most of the Javascript tooling ecosystem, you can do things like import picture from 'image.png', which obviously isn’t Javascript. The assumption is that some tool will know how to transpile the referenced file into Javascript so this works correctly. All types of assets and alternative syntaxes, such as JSX, work this way.

Typescript, on the other hand, expects you to either use a blank extension or the .js extension, which is different from how the rest of the ecosystem works. This causes friction for tools like Deno or rollup.js that expect the original file extension.

If tsc wanted to work more like the rest of the world, it could allow .ts as an extension, and then transform that to .js as part of stripping types at build-time. This is obviously a large change to the way the tsc compiler works. On the other hand, there is a wave of alternative tooling based on Babel and Sucrase beginning to enter the ecosystem, so perhaps there is a long-term benefit in aligning with those tools’ way to doing things.

Would the TypeScript team be open to adding "module": "deno" to the tsconfig? That way we can support using the .ts extension natively, without needing to resort to something like kitsonk/deno_ls_plugin as a workaround. It could also try and enforce it as well, so if you try and do

import module from 'module';

it would show an error like Cannot have an extensionless import with module:deno (the only imports that are allowed are full URLs, and relative imports starting with ./ or ../). A configuration like that could also support natively searching the $DENO_DIR/deps folder for types, since we currently need to use a path setting to workaround that. On top of this, automatic imports could work properly as well, since they currently always do the extensionless import (meaning you have to manually edit it anyway).

@hooper-hc I think we can set tsconfig as a temporary solution like this:

{
  "compilerOptions": {
    "module": "amd",
    "target": "esnext",
    "baseUrl": ".",
    "paths": {
      "http://*": ["../../../.deno/deps/http/*"],
      "https://*": ["../../../.deno/deps/https/*"],
      "*.ts": ["*"]
    }
  }
}

The Deno developers are not getting the respect they deserve here. They made an amazing runtime based on TypeScript, but TypeScript developers won’t add a flag to allow it to work properly. How can this sorry situtation go on for so long?!

Not being able to use the .ts extension on imports is causing massive pain and problems for Deno users, please help us!

Deno’s a great idea, but trying to convince the TS team to explicitly allow Deno to resolve modules that way to me is a losing battle. It’s much easier for Deno just to handle it because (a) way faster to do so, less effort needed and (b) convincing the TS team to rewire its internals like that is a very uphill battle.

If tsc wanted to work more like the rest of the world

TS is becoming increasingly dominant, it’s a good strategy to be as compatible as possible to TS conventions including their tooling. Otherwise projects like Deno will never get traction due to the divergence in something as fundamental as module resolution

@jpike88 I disagree. I didn’t realise this issue existed. There were a couple other issues semi-related which we were tracking. This issue doesn’t say anything about the intent of the team. It is still labelled as a question and it could be argued it really is a duplicate of #16577 or #18442.

Ryan’s comment though gets to the heart of the problem, that they can possible write out something that satisfies every host, so they restrict it to the most common situation today, which is Node.js’s CJS way.

I still think (and I thought I said this in an issue before) is that there might be time for "moduleResolution": "literal" which would do what it says on the tin, and allow TypeScript to assume that whatever runtime host would figure it out/change the module specifiers.

its not actually Deno specific

without possibility to explicitly define extension many JS devs will have problem

for example in our vue project we always specify extensions, or else we’ll have problem in situation like

./component.vue
./component.ts
import component from './component';

This issue needs to be reopened.

@reggi remove ./ I hope that in the future, we can use a configuration similar to module:deno to simplify the operation.

just needs to remove the .ts extension name


- import * as UIComponents from './index.ts'

+ import * as UIComponents from './index'

How come this issue is open for 5 years (!!) with no answer or progress whatsoever?

last post one year ago and first post 2018 and no real solution?

If I don’t do a .ts it doesn’t find my imports if I do it’s all red. Putting a // @ts-ignore over every line destroys the clarity.

How can such a serious annoying bug not have a reasonable solution within 4 years.

As others have alluded to, the ESM spec requires an extension, and so in an ESM based world, omitting the extension is definitely going against the grain, and I expect will be so more and more going forward.

In addition, since these ESM based tools are the ones wanting to provide a first class TypeScript development experience, they will naturally be relying on the extension to power said experience. Thus, with the current choices being

  • no extension
  • or use .js

It’s really between a rock and a hard place for a lot of us in this thread, and made all the more unfortunate with this issue being closed and dismissed as a question and pushed off to SO. Is there is no room for conversation on this one from the TS team? 🙏

This seems like a duplicate of #11901 which was unfortunately closed and silenced. This is important for Deno as was said before and I hope TypeScript will make this extension check configurable or even better remove it altogether.

Wait, is the current state of things that it is impossible to write a “cross platform” TypeScript library that works in Deno, Node and on the frontend? This really makes me question the maturity of the language.

If anyone here was just looking for a way to be able to run your TypeScript within both the context of Node.js and Deno, know that Webpack + ts-loader will let you keep “.ts” in your imports.

As of about a month ago, you can use:

"allowImportingTsExtensions": true

In your tsconfig.json to enable *.ts imports.

TypeScript users on Snowpack are also running into this issue. ESM imports in Snowpack are based on the source filename, so import './file.ts' and import Counter from './counter.tsx' are both expected to work. We ask TS users to use the “.js” file extension as a workaround, but we’re looking to add new features that might break this for them entirely.

It feels odd that TypeScript wants to both stay out of import resolution (the right call, imo) but also put arbitrary limits in place. I’m +1 this warning as a default to protect new users from footguns in most projects, but projects like Deno and Snowpack should be able to suppress this.

This is a huge problem. As currently it’s impossible to share files between Deno Backend and React/Svelte Front-End.

The truth for me is that this is a problem of your setup/bundling process. What I did was to remove the extension and configure webpack to resolve .ts files with:

// in webpack.config.js
resolve: {
  extensions: [".json", ".js", ".ts"],
}

This thread is NOT a question, it is a feature request. Please can someone correct the label and re-open it? Manually adding // @ts-ignore to every import is not an acceptable solution.

@jacobmischka Thanks for the link. I think both sides could be pleased if one would consider typescript imports import b from "b.ts" as typescript code instead of javascript code…

Emit clean, idiomatic, recognizable JavaScript code.

typescript -> transpile -> javascript .ts -> transpile -> .js

@RyanCavanaugh

I’m no fan of the typescript syntax

TypeScript is a great language. And node.js is a good platform. But deno is better. And we need support for both platforms at once, please 😃

reopen this issue?

since typescript is not going to fix this how about deno automatically changes all import paths with no extension to .ts at runtime

I also use Deno but I think the problem here is not about .ts vs no .ts. It’s more about the ability to allow tsc to ignore any error number. For example, something like tsc --ignore TS2691.

a “flag” would solve the issue

--i-want-write-extension-explicitly

i also saw a PR here, which added exactly that, but unfortunately core team blocked it ¯_(ツ)_/¯

and so far i see its not a technical or an architecture issue - somebody in TS core team JUST WANTS IT, and thats it, no reason

@kitsonk

This isn’t a barrier for Deno.

but this is a barrier to the unification of two worlds: Node and Deno. How can I write a typescript that will work on both platforms at the same time if you guys have religious disagreements about importing local files with or without extensions… I’ll have to choose a side

Why is this closed? Certainly not Deno specific especially with the rise of mjs

This is now a more pressing issue given that ts-node and node seem to have FINALLY settled on a stable loader API. And we can almost disable all the “magic” by using TS 4.5 node12 mode. Meaning import './my.ts' now natively makes sense in node (with a loader) and deno.

This matters a lot to remove confusion in development and make writing generators easier. Currently generating deno code and node code using the same generator is not easy, as the whole import block has to be rewritten… which is technically completely unnecessary.

This is one of those reasons why i stick to vanilla js instead. I have never been a fan of compiling and TS weird syntax ontop of js. It don’t really fit into a loosed typed language anyways. Having support for typescript http-imports in Deno is beyond my understanding. You basically have two JIT compilers. TS > JS > V8 and the code will take longer to load

And now this with extenssonless import, cjs, esm, mjs, mts and cts extensions becomes a total mess. Many tools out there don’t even’t support mts or cts files and don’t know how to resolve the path/import… and to support esm you have begun to enforce .js extension when you are actually importing a ts file

i will stick to vanilla js + jsdoc and even d.ts files and refactor all my ts code to js. You don’t really need typescript syntax to have typed support. beside, it looks like we could have optional typing support nativly in js one day… then TS will become totally obsolete

Is there an official statement about this issue? I don’t know what is true and what speculation about the reasons. But I also don’t know what exactly is holding this back. The typescript goals state

Align with current and future ECMAScript proposals.

Since imports take the extension (imo the comment about bundlers in the module-name description is out of place) and with import assertions on the way this seems to be a no-brainer.

Ya know, we could just stop using vsc.

Removing the .ts when importing solved it for me. i.e import Example from './examplefolder/example'

MY SOLUTION: For me was enough to remove the file extension .ts from the import and the error went away.

So many issues that were created recently got attention and were resolved.

This issue was created on Oct 1, 2018, has 57 comments, a neat proposed solution by @luvies (https://github.com/Microsoft/TypeScript/issues/27481#issuecomment-464456102), hundreds of people interacting and quite a few willing to help, yet it is completely ignored and silenced.

“Open Source”

monke creates humanity typescript destroys

ditch typescript return to monke

I would also like to mention eslint rule, which greatly explains why explicit extensions are a great thing

https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md

Is this fixed? Importing without extension is not part of the JS anyways, using extensions should not display an error.

why not? reason?

They havent for almost 3 years.

I am part of the Deno core team. I agree that the TypeScript compiler shouldn’t get involved in rewriting module specifiers. The internals of Deno suppress this diagnostic message and the vscode plugin for Deno also supresses this message. This isn’t a barrier for Deno.

Trust me that there isn’t some hidden Microsoft/Node.js hidden cabal suppressing Deno. The TypeScript core team, member of the Node.js community and the Deno core team regularly talk to each other and collaborate.

For anybody having recent troubles with this, I will say that the deno_ls_plugin despite being archived achieved exactly the result I need. This issue that references the plugin is how I found out about it.

My specific use case is that I am working in an environment with typescript code shared between the client and the server using symlinks. The server is written with deno in mind, and the client is written with regular typescript and phaser3. The bundler I am using, parcel, can handle typescript importing .ts files (at least with parcel-bundler ^1.12.4). That leaves the intellisense to be fixed.

deno_ls_plugin works great for me, because it literally just patches .ts module resolution. Perfect! That means I can import the shared code, and have the shared code be written with deno front and foremost in the mind, and patch the intellisense for the typescript client side of things.

For starters, I ran the yarn add typescript deno_ls_plugin --dev command to install it. After seeing that the intellisense wasn’t fixed, I noticed some tiny text at the bottom of deno_ls_plugin’s readme, to use the workspace version of typescript.

For anyone else a bit confused about how to do that, here’s what I did: First, I installed deno_ls_plugin and typescript as development dependencies, and updated tsconfig.json to include deno_ls_plugin as a plugin

{
  "compilerOptions": {
    "plugins": [{ "name": "deno_ls_plugin" }]
  }
}

Then, I clicked on a typescript file and clicked on the version in the bottom right corner. version Then, I chose to select the typescript version here and chose the workspace version. image In my specific case, I have also set typescript.tsdk in .vscode/settings.json but I don’t know if I needed to. settings.json

If anyone else is also trying to share deno code with typescript code, I used symlinks to link to the core code in both the server and client, and had the code inside the symlink reference a deps.ts file outside of it for dependencies (since import_map is kinda meh atm) so that the typescript version can import the npm package and the deno version can import the URLs. symlink madness

Hopefully this little message might help anybody having similar issues with trying to share deno code between a classic typescript project and a deno project.

Similar issue occurs if you want to directly import an .mjs file e.g. import { forEach } from https://unpkg.com/iterall@1.2.2/index.mjs

As of about a month ago, you can use:

"allowImportingTsExtensions": true

In your tsconfig.json to enable *.ts imports.

When doing do, I get the following error instead.

tsconfig.json:14:35 - error TS5096: Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set.

14     "allowImportingTsExtensions": true,
                                     ~~~~

Found 1 error in tsconfig.json:14

I just want to be able to use TypeScript and ES6 modules together :c

I use custom loaders in Node.js and I cannot stop VSCode from issuing error messages telling me that imports “cannot end” with various file extensions, which is now strictly false no matter what runtime is in use. Why not allow users to set an option to avoid this?

just needs to remove the .ts extension name

- import * as UIComponents from './index.ts'

+ import * as UIComponents from './index'

Unfortunately that wouldn’t work in Deno.

Currently generating deno code and node code using the same generator is not easy, as the whole import block has to be rewritten… which is technically completely unnecessary.

there’s a lot more compatibility issues between node and deno, especially url imports

the only viable option for you to write in typescript for one platform and compile it to js where it use full path with .js extension never should you publish something as typescript cuz that don’t work for all 3 major platform (deno, node & browsers) this hole module loader for typescript is insane. we want fast and precompiled code so that it loads faster

Or maybe let’s ask @ry to replace the Typescript with Flow in Deno! There is no need to change the file extensions in Flow 😉

Screenshot 2021-05-12 at 10 48 04 Screenshot 2021-05-12 at 10 48 15

This is nonsense.

The Deno extension for vs code is nice, but it doesn’t solve the problem, it just suppresses the error in the editor. I have a library that I want to build for deno and the browser, but I can’t because tsc will throw.

Is there is no room for conversation on this one from the TS team? 🙏

https://github.com/microsoft/TypeScript/issues/27481#issuecomment-948141952

I love TypeScript the language, but I agree this won’t be fixed. Sadly the JavaScript crowd doesn’t seem to care about traditional values like engineering quality or developer experience. Hot New Features or die, seems to be the prevailling sentiment.

I just use Atom with no typescript plugins. It doesn’t crash my ubuntu.

Thank you @Higgs1. I will add a dynamic imports fix with string literals on the next forthcoming version. Although, dynamic imports with variables would be out of the scope of the tool. As you mentioned, that is indeed a hack while the tsc team does not fix that in the compiler itself. I’ll be glad to deprecate the package as soon as we see tsc doing that job for us.

In the meantime, to deal with dynamic imports with variables I think the best option would be to use tsc as a type checker and type generator, and use Babel’s @babel/plugin-syntax-dynamic-import or use Babel ^7.8.

last post one year ago and first post 2018 and no real solution?

If I don’t do a .ts it doesn’t find my imports if I do it’s all red. Putting a // @ts-ignore over every line destroys the clarity.

How can such a serious annoying bug not have a reasonable solution within 4 years.

Beats me!

@VidarDev check @vasujain’s comment

Actually this error will be resolved if you use deno extension with VScode

Doesn’t solve every case but you don’t need to // @ts-ignore.

The reason there is no solution in 4 years is because this goes against TS team’s principles. Not that I agree with them but that’s the case.

beside, it looks like we could have optional typing support nativly in js one day… then TS will become totally obsolete

Developed by TC39 team: object-oriented and spaghettified 🙈 God spare 😅

Note more discussion on this is happening at #37582

@FedericoCapaldo This issue is all about keeping the .ts extension and being explicit about what file you want to import instead of having to guess if you meant to import foo.js or foo.ts or foo/index

@Hulkmaster

It looks like we need a shiny new typescript. This one is stuck with its legacy problems and can’t (or don’t want to) implement imports with extensions. The deno team seems to be planning to write their own typescript (in rust, I suppose 😃

I agree with the comments above. It’s too bad the problem hasn’t been solved yet. I found an extensions for vscode that should help, but unfortunately it doesn’t work properly. Anyway, I’ll leave the links here:

  1. https://github.com/justjavac/vscode-deno
  2. https://github.com/axetroy/vscode-deno

I’m having the same issue with moq.ts package. Any solutions? https://www.npmjs.com/package/moq.ts

Actually this error will be resolved if you use deno extension with VScode

I, as I believe many others in this thread, don’t want TypeScript to touch JavaScript files, or any files at all, because we’re only using TypeScript for checking and not compilation.

I take benefit of typescript with js, JSDocs and followJS, checkJs. (even use // @ts-check sometimes) I don’t like to have to transpile my code and i don’t like the syntax either… i don’t like what isn’t standardized I only use it for type definitions… I write what is cross compatible and works with browser, deno & nodejs imports without having to compile everything to one bundle where only 10% of your codebase is used.

I’m only here cuz my team works with typescript and i want to feel more at home. I do not have this problem when i write vanilla js.

Beside this issue is a huge issue among Deno developers that threat extenssionless differently

Forking Typescript is not a solution. The open source community needs to constantly steer towards consistency.

The root of this issue is an inconsistency in Typescript runtime environments.

why not? reason?

@zraineri

I have read several threads dealing with this issue. To summarize, core developers just don’t want to do this. They say that it can break other things and that the import algorithm is already quite complex and so on.

Consider me crazy, but it seems to me that there was some corporate solidarity here. The company has spent a lot of money on the node (npm). And doesn’t want some upstart to rob them of their profits with her own hands… So I don’t think you can expect much friendliness towards deno from vscode or typescript

Luckily, you can use a plugin that already does more than you ask for and will only get better. https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno

But the problem is, not only Deno, but also regular js https://github.com/microsoft/TypeScript/issues/27481#issuecomment-664401169

@samuelgozi I agree 100%. This is the main reason why I do not yet consider Deno as a replacement for the node.js on the server. A good web frameworks for Deno is already available, and only TYPESCRIPT stands in the way of this beautiful dream

@danbulant I am still seeing the error using the vscode_deno plugin.

I have this issue whenever I import file from deno? any solution to fix this except adding // @ts-ignore ?

@danb4r Thank you for trying to singlehandedly fix a critical tsc bug. Although using sed is rather hacky, it seems to work very well. It doesn’t support dynamic imports (even with a string literal, e.g. const foo = await import('foo')) though, Is that something you plan to add in the future?

While there is no fix from tsc itself (the #11901 has been closed to collaboration since Jul 2018), I had to write this small script called fix-tsc-es-imports that can be integrated into the building process just after tsc.

It adds a .js extension to all relative imports and exports in the code generated by tsc, solving the issue.

Thanks for the hint, I found the issue. I exported this as part of a npm package but moq.ts was not in the dependencies, only in devDependencies. If you then use the package in a project that does not include moq.ts, the issue pops up.

While I would absolutely love this to be fixed, “open source” means you’re free to fork the project and do what you want with it, not that its maintainers are obligated to bow to your whims. Open source is working just fine here.

JavaScript crowd doesn’t seem to care about traditional values like engineering quality or developer experience

Therefore, for now, we tolerate Typescript while waiting for the moment when it will be possible to comfortably write the front-end and back-end in Rust 😃

Following @TicTak21: The links he mentioned are both deprecated now in favor of the official deno plugin: https://github.com/denoland/vscode_deno This extension fixes the .ts and URL imports (so no more errors) correctly,