'.js' files in TypeScript - why?!

Поделиться
HTML-код
  • Опубликовано: 28 июн 2024
  • 00:00 The Problem
    00:56 The Solution
    01:20 Node Wants .js?
    02:08 Why Not .ts?
    02:41 What If I Don't Want .js?
    Article: www.totaltypescript.com/relat...
    Become a TypeScript Wizard with my free beginners TypeScript Course:
    www.totaltypescript.com/tutor...
    Follow Matt on Twitter
    / mattpocockuk
    Join the Discord:
    mattpocock.com/discord
  • РазвлеченияРазвлечения

Комментарии • 109

  • @benjidaniel5595
    @benjidaniel5595 8 месяцев назад +119

    I’m surprised that the TS team don’t let you simply import .ts and then have TSC compile the imports out as .js. Guessing they have their reasons though

    • @steamer2k319
      @steamer2k319 8 месяцев назад +7

      Yeah. This going to lead to endless migrations back and forth. Merging with a team that uses a bundler? Time to change all your imports. Extracting some code out to a re-usable library where bundling is deferred? Time to change all your imports back.

    • @jonkoops
      @jonkoops 8 месяцев назад +3

      @@steamer2k319 No, the `.js` extension is supported by bundlers. So there is no need to do this.

    • @StarOnCheek
      @StarOnCheek 8 месяцев назад +2

      Their long term game here might be to phase out the tsc compiler

    • @artemsapegin
      @artemsapegin 8 месяцев назад

      Yeah, thinking of compiled code feels so 2000s…

    • @dealloc
      @dealloc 8 месяцев назад +3

      Atleast two reasons why;
      The TypeScript team has stated that they don't want to rewrite your JS code, only remove TS type information (and even that they want to avoid, with the "types as comments" proposal). While it's true that non-const enum already does this, it's actually just a remnant from legacy TS to make it backwards compatible before they decided against rewriting JS (apart from bundling it against your target runtime).
      It would also have additional impact on transpilation times; aside from just transforming the extension, it would also have to verify that this path actually exists (requiring I/O to check if file exists) which is slow. Without this vertification, it would be unintuitive if TS happily transformed module paths, and result in runtime errors. You'd also have little to no control over _how_ this transformation is done, adding a ton of headaches-you really don't want to debug a transpiler's implementation, only your own code.

  • @Ostap1974
    @Ostap1974 8 месяцев назад +12

    I fully understand the argument why TS decided to go with it. But if I was on that meeting, I would have voted againt it.

  • @madzzz0
    @madzzz0 8 месяцев назад +54

    I am down with adding `.ts` extension but `.js` extension for `.ts` file is just too counterintuitive for me & confusing. The transpiler should handle that or we can always stay in bundler moduleResolution.

    • @BarbaRuiva5
      @BarbaRuiva5 8 месяцев назад +7

      It feels like adding .o to c code.. I am using TS as a compiler, I do not want to know what happens inside

    • @StarOnCheek
      @StarOnCheek 8 месяцев назад

      "or we can always stay in bundler moduleResolution" yep, that's what it is for...

    • @StarOnCheek
      @StarOnCheek 8 месяцев назад +1

      @@BarbaRuiva5 using tsc should already be a sign that you are doing something wrong

  • @franky47
    @franky47 8 месяцев назад +9

    Perfect example of an abstraction leak.

  • @ApprendreSansNecessite
    @ApprendreSansNecessite 8 месяцев назад +30

    This is one of those things that makes interop a nightmare. You could literally get stuck or have to change the way you import everithing because you added one build step or tool

    • @jonkoops
      @jonkoops 8 месяцев назад +3

      It's actually more compliant with standard JavaScript to add `.js`, any modern tool should be able to handle this.

    • @ApprendreSansNecessite
      @ApprendreSansNecessite 8 месяцев назад +4

      @@jonkoops I don't think so. It's called "source code" for a reason, but it's an opinion

  • @rodrigoleitao25
    @rodrigoleitao25 8 месяцев назад +7

    This is literally the thing preventing me from updating to esm

  • @scratchcoding7690
    @scratchcoding7690 8 месяцев назад +26

    One of the reasons why I love Deno is that you don't need to worry about the Typescript Configuration :D

    • @mattpocockuk
      @mattpocockuk  8 месяцев назад +6

      Yeah I'm starting to see the appeal

  • @megaxlrful
    @megaxlrful 8 месяцев назад +20

    We truly live in the worst timeline for Typescript.

  • @stroiman.development
    @stroiman.development 8 месяцев назад +7

    AFAIK, another option is to use Node 20 - it should support imports without extensions. Maybe a bit longer startup times, but that is seriously not a problem for me.
    I always loved the extensionless imports. When a file grew too big, I changed it into a directory with an index file, and none of the existing code would be affected.
    Since it's not LTS yet, I haven't tried it yet, so I may be mistaken ...
    (until mocha watch mode supports ESM modules, I stick with commonjs modules. The number one important time to measure is not startup time, but feedback time from I save a file until relevant unit tests are run. Currently that is typescript compiler in watch mode, and mocha in watch mode, monitoring the ts build output)

  • @dinckelman
    @dinckelman 8 месяцев назад +5

    These kind of issues and disagreements make me want to write TS less, as the time goes by

    • @mjerez6029
      @mjerez6029 3 месяца назад

      This is all because TS team paranoia of just being a type checker and nothing else...
      Really getting sick of it, we would have so many great things if it wouldn't be because of that hardcore limit.

  • @onlywei
    @onlywei 8 месяцев назад +11

    Come on... developer experience is more important than Node internals experience

  • @moritz_p
    @moritz_p 8 месяцев назад +26

    I'm sorry but I completely disagree with you. You saying it kind of makes sense because your compiled code is in .js files and it will consume those is just beyond the point. As you're saying, it's the *compiled* code we are talking about. You don't reference the compiled code from your Typescript files, but you reference the uncompiled Typescript code. They should simply adjust the file extension from .ts to .js in the compilation step.

    • @erikslorenz
      @erikslorenz 8 месяцев назад +12

      Yeah I'm down with file extensions, but there is no amount of mental gymnastics that can make using .js instead of just having the ts compiler change it is anything but silly

  • @beetrootpaul
    @beetrootpaul 8 месяцев назад +4

    My main issue with ".js" imports (even though I consider them more correct) was the lack of support in WebStorm IDE. Whenever I copy-pasted some thingy, the IDE was auto-generating an import, but it was with ".ts" extension (or extension-less at all, depending on the project config)

  • @nader2560
    @nader2560 8 месяцев назад +18

    I think next we should target .bin extensions instead of .js and move straight to machine compiled version of the code that would make much more sense than simply stopping at the .js part, why not go all the way it also makes sense 😂

    • @Rudxain
      @Rudxain 8 месяцев назад

      Or maybe byte-code, lol. There have been proposals for a stable BC spec, but such standardization will force all JS engines (V8, SpiderMonkey, ...) to have extremely similar BC implementations (which would make their performance similar) and it would prevent them from updating it internally (because stability requires retro-compatibility). That's how WAsm was born.
      Funnily enough, there are already standalone WAsm runtimes similar to Node/Deno, so your idea is almost reality

  • @eulucaspedroabreu
    @eulucaspedroabreu Месяц назад

    Was in dare need of this explanation! Thank you, Matt!

  • @davidadamson1588
    @davidadamson1588 8 месяцев назад +4

    sadly this is the reason, I still target commonjs when transpiling using tsc

  • @proosee
    @proosee 8 месяцев назад +8

    I'm sorry, I don't get it, compiler is made to traverse us to the other side with dry feet, at the moment of compilation you NEED to have that file at THIS destination, so compiler will know what you meant when referring to .ts file and should automatically convert it to a valid .js import - simple as that. It's like you would be writing something in a native language and was wondering how the linker is gonna load/link your dll/so/whatever files - if you are not doing something fancy you don't care, you just import/include your source file or reference an external library and forget that linker even exists.

  • @ColinRichardson
    @ColinRichardson 8 месяцев назад +5

    I sadly worked all this out by myself.. I am not usually one for hand holding, but I feel something like this would have been nice to have had Typescript hold my hand a little more...

  • @jordancutler7552
    @jordancutler7552 8 месяцев назад +2

    Super informative, Matt. Thank you!

  • @benchilcott6908
    @benchilcott6908 8 месяцев назад +5

    Surely having a compiler means you shouldn’t have to think about the structure/files of the compiled output? I’m curious why TSC can’t figure out which files you’re talking about and add the right extensions later..

    • @mjerez6029
      @mjerez6029 8 месяцев назад +1

      Im pretty sure tsc can but thing tsc doesn't want to do anything that could be considered changing the code.

  • @thornycro
    @thornycro 8 месяцев назад +6

    Or... instead of node, use bun, import without extension and have it run much faster... It's not about the speed, it's about two different team epeen contest (ts and node), going back and forth and not wanting to fix this.

  • @HavenB3
    @HavenB3 8 месяцев назад +1

    If your goal is getting esmodules from TS, the easiest workaround for now that I’ve found is to just use esbuild for all bundling/transpilation, having tsc only do type checking

  • @AqgvP07r-hq3vu
    @AqgvP07r-hq3vu 8 месяцев назад

    I desperately needed a video about this

  • @suslamo
    @suslamo 8 месяцев назад +8

    And that folks is why Deno is better :)

  • @BalintCsala
    @BalintCsala 8 месяцев назад +6

    I get why it wants to work like this given how typescript is structured, I'm just very confused why TS is so hell-bent on not changing your code. Sometimes it feels like you could "compile" TS to JS with a single `code.replace(/very long regex/g, "")` call

    • @mattpocockuk
      @mattpocockuk  8 месяцев назад +3

      They (and I) see that as a benefit - a thinner layer is easier to conceptualize and remove.

    • @BalintCsala
      @BalintCsala 8 месяцев назад

      ​@@mattpocockuk that is true, but at the same point it makes it considerably less powerful and I'm not just talking about how you have to put the extension there. This same limitation stops operator overloading from being implemented and makes overloaded functions much less useful.
      I wish you could have those features without giving up the comfort of working on the web by using a native language compiled to wasm

    • @mjerez6029
      @mjerez6029 8 месяцев назад

      We could have runtime types by now id typescript team would reconsider their goals. Hope soon we can see a bun equivalent to typescript, just so there is some competition.

  • @Keisuki
    @Keisuki 8 месяцев назад +30

    Nope. This is stupid. In no other language do we have this problem. My kotlin code is compiled to any number of .class files, do I have to pre-empt where those files will be and what they'll be called? No. My python code is compiled to .pyc files, do I have to import the .pyc files? No.

    • @inversemetric
      @inversemetric 8 месяцев назад

      💯

    • @DirkLuijk
      @DirkLuijk Месяц назад

      It’s because ES modules are designed to also work on the web. You don’t want the browser to do a lot of roundtrips just to guess where the actual file is located on the server.

  • @abdallahm96
    @abdallahm96 8 месяцев назад

    As someone who eventually has to bundle my code to be ran on the browser, do I use the bundler resolution, have compiled bundles as es6 or later, then either use as is or transpile to es5 (for legacy purposes)?

  • @AqgvP07r-hq3vu
    @AqgvP07r-hq3vu 8 месяцев назад +1

    you looked nice in the TS documentary btw

  • @maelstrom57
    @maelstrom57 8 месяцев назад

    In Deno, since you can import a JS file into a TS file and vice versa, you have to use the actual file extension, which is much better.

  • @killymxi
    @killymxi 8 месяцев назад

    My output extensions are a bundlers concern.
    Especially because I'm building for both esm and cjs.
    So, I use Rollup and all of "moduleResolution": "Bundler", "allowImportingTsExtensions": true, "noEmit": true.
    (and rollup still issues a warning about allowImportingTsExtensions, even despite it says right there it is fine with noEmit)

  • @totetoBT
    @totetoBT 8 месяцев назад +1

    Caught me off guard that I have to use extensions for relative imports, but not for external dependency imports

  • @thegrumpydeveloper
    @thegrumpydeveloper 8 месяцев назад +2

    I’m all for making things faster, but feels like this could be a vscode extension to auto add the file extension. Pay the price once on save and never again. 99% of the time it’s easy to guess the extension and the rest can be left as errors.

    • @mattpocockuk
      @mattpocockuk  8 месяцев назад +2

      TypeScript does this automatically - it's built in to VSCode. Also works with auto imports and moving files around.

  • @tanzeelabdulwahid8734
    @tanzeelabdulwahid8734 8 месяцев назад

    Great

  • @AlexanderDemin
    @AlexanderDemin 8 месяцев назад

    Deno mandated the explicit use of .ts extension in imports for getgo for exactly that reason.

  • @redsun9594
    @redsun9594 8 месяцев назад +3

    We need to move away from JS asap, thing will just keep on getting worse from here 😅

  • @Gabriel-iq6ug
    @Gabriel-iq6ug 8 месяцев назад +1

    I like so much this approach because I like to know how it works under the wood. But many other dev don't really want to know and are concerned about the way it looks

  • @EyalShalev
    @EyalShalev 8 месяцев назад +1

    IIRC the reason typescript doesn't allow .ts imports is that they compile one file at a time.
    Deno made .ts imports work by hacking into how typescript works.

  • @Karg537
    @Karg537 8 месяцев назад

    How To Confuse Your Jr Dev (or Dev in General)?

  • @neociber24
    @neociber24 8 месяцев назад +1

    This become unbearable when you use the .mjs or .cjs extensions, tsc do not allow those

    • @mattpocockuk
      @mattpocockuk  8 месяцев назад

      Yes it does - you can use .mts or .cts extensions and use moduleResolution: NodeNext.
      www.totaltypescript.com/concepts/mjs-cjs-mts-and-cts-extensions

  • @Manish___Choudhary
    @Manish___Choudhary 8 месяцев назад +2

    Make video on ark types please

  • @flammea_
    @flammea_ 8 месяцев назад +1

    I think I finally got it.
    - you use tsc to transpile your .ts files into .js files and put them into the folder called dist.
    - you then decide to execute your main ts file with a tool like tsx that doesn't require you to transpile .ts files into .js files first to understand it.
    - tsx sees the foo.js import and goes straight to /dist/foo.js to execute it as a js file. If the imported file had been .ts instead, tsx would have to first transpile the file into js and then execute it.
    If this is actually what it is for, my question is, why not execute the transpiled js file with node rather than tsx if you already have access to the transpiled code?

    • @mattpocockuk
      @mattpocockuk  8 месяцев назад +1

      tsx runs on source files. node runs on transpiled JavaScript.

    • @flammea_
      @flammea_ 8 месяцев назад

      I'm still lost lol. if it's not for tsx then what is it for? what tool benefits from js imports in ts files

    • @mattpocockuk
      @mattpocockuk  8 месяцев назад

      @@flammea_ Node. You compile this code to .js using tsc, then Node can run it.

    • @Gabriel-iq6ug
      @Gabriel-iq6ug 8 месяцев назад

      @@mattpocockuk This comment of @flammea_ illustrate perfectly why so many dev are frustrated. They think TS run the code. It looks so basic but you should consider to make a video to explain "You compile this code to .js using tsc, then Node can run it."

  • @Gabriel-iq6ug
    @Gabriel-iq6ug 8 месяцев назад

    I guess many dev don't make the difference between writing code and executing code. That's why they don't understand why .js is needed here

  • @Rudxain
    @Rudxain 8 месяцев назад

    0:50 This is like The Password Game, lol

  • @ychinamale
    @ychinamale 8 месяцев назад +1

    This is why Bun > Node.
    I'm kidding. 😜
    Am I kidding? 😏

  • @jessta314
    @jessta314 8 месяцев назад +13

    This is a mistake that they will regret and backout at a later time.

    • @IvanKleshnin
      @IvanKleshnin 8 месяцев назад +5

      Exactly. Like .mjs which noone uses. They are losing the grip with reality.

  • @iangrant4756
    @iangrant4756 8 месяцев назад +1

    What a ridiculous change! I get the reasoning and reckon it’s a load of codswallop. There was nothing wrong with the way it was working, but now you have to import a file that doesn’t exist? Just because … well, for no particular reason at all! So, so ridiculous.

  • @slava_trushkin
    @slava_trushkin 8 месяцев назад +3

    Unfortunately this doesn't explain why we can't import `.ts`, then, when file is compiled, TypeScript wouldn't change that to `.js`. Compiler changes extensions of files it creates, so why can't it change extensions in imports?
    I'd rather:
    - Add bunch of exports in package.json
    - Not use TypeScript at all
    than add `.js` to imports, which points to files that do not exist. Absolutely counterintuitive nonsense from TypeScript team.

  • @worgenzwithm14z
    @worgenzwithm14z 8 месяцев назад +1

    Another reason to use esbuild I guess

  • @mariusp.2478
    @mariusp.2478 8 месяцев назад

    And to make it more confusing - if you're only importing types, then a no extension import will still work

  • @kbsanders
    @kbsanders 8 месяцев назад +3

    This feels like a dumb move. If anything we should be using `.ts` and the compiler should convert them to `.js` in the output.

  • @UocLv
    @UocLv 8 месяцев назад +1

    Thanks, Satan. I can't wait anymore, i need native type support in JS, this is so stupid.

  • @EvitanRelta
    @EvitanRelta 8 месяцев назад +1

    The "s" sounds (ie. sibilance) in the video's audio is too sharp. Hurts my ears when listening :(
    Might wanna do some de-essing on future audio

  • @ShinigamiZone
    @ShinigamiZone 8 месяцев назад +3

    I will never use NodeNext due to this

  • @avid459
    @avid459 8 месяцев назад +1

    Do you import compiled .class files in java
    Or import .pyc in python?
    Binary files in C, zig or rust?
    Or similar story with, elixir, groovy which are transpiled.
    Why does typescript think they are any smarter than all the existing languages and make it painful for all the Devs. 🤦‍♂️🤦‍♂️

  • @danilo3684
    @danilo3684 8 месяцев назад

    Well... Actually, I think is better:
    tsConfig: {
    allowImportingTsExtensions: true,
    noEmit:true,
    moduleResolution: NodeNext
    }
    And use xwtsc to build or run

  • @guilhermeferreirabr
    @guilhermeferreirabr 8 месяцев назад +1

    IMO it seems that Typescript innovation is coming to an end, so we better keep fighting for nitpicking situations to stay relevant... 🙄

  • @MrWholphin
    @MrWholphin 8 месяцев назад

    TS is the tail wagging the dog

  • @Kampouse
    @Kampouse 8 месяцев назад

    bun

  • @erikslorenz
    @erikslorenz 8 месяцев назад +3

    Not using file extensions was dumb, rhe whole index.js thing was dumb. Using .js instead of .ts is also rrally dumb. It literally has a transpolation step. Just change it there lol

  • @sidma6488
    @sidma6488 8 месяцев назад +2

    I dunno how I feel about this. :/ Doesn't Typescript transpiles to Javascript anyway even with NodeNext? Boottime should be exactly the same with all options.

  • @inversemetric
    @inversemetric 8 месяцев назад +1

    This will go down in history as one of those insanely stupid decisions that'll eventually be undone. With everything typescript is doing to the code, the least it could do is replace a `t` with a `j`. Give me a break

    • @mattpocockuk
      @mattpocockuk  8 месяцев назад

      TypeScript NEVER changes runtime behaviour. So, doing this would break a key rule.
      But I sort of agree - TypeScript kind of 'owns' the .ts extension, so it makes sense to me that it would change .ts to .js.

  • @Matt23488
    @Matt23488 8 месяцев назад

    Doesn't bother me as long as auto-imports put the correct thing. If it doesn't, that will be really annoying and I'll have a reason to be pissed off.

    • @mattpocockuk
      @mattpocockuk  8 месяцев назад

      Yep, auto-imports just work.

  • @jeremytenjo
    @jeremytenjo 8 месяцев назад

    .js is the best because it makes it possible to share code between node and browser environments (obv when node specific functions not included)

  • @gabrieljose7041
    @gabrieljose7041 8 месяцев назад +3

    I'm surprised of how much people don't know the standards (not referring to Matt) until these days, but this is how esmodules works

    • @mattpocockuk
      @mattpocockuk  8 месяцев назад +2

      Yep, it's just the bundlers obscured it for so long.

    • @QwDragon
      @QwDragon 8 месяцев назад +2

      Standarts don't6 work with ts. Compiler should compile to standarts. It's an awful idea to forse writing this.

    • @gabrieljose7041
      @gabrieljose7041 8 месяцев назад

      @@QwDragon I don't think they should. I actually think that keeping .js is the right thing to do, because the end code is js and the standard is for js not ts, let it turn ts to js is like hiding what you're actually working on. But it sure can have an option to do it if someone prefers

  • @aleksd286
    @aleksd286 8 месяцев назад

    Solution: Use Bun

  • @mjerez6029
    @mjerez6029 8 месяцев назад +2

    Nope thanks, I would never use .js extension on a ts file 🙅🚫

  • @DobesVandermeer
    @DobesVandermeer 8 месяцев назад

    This whole thing is going to turn out to be a big mistake and get fixed later, in pretty sure of it

  • @akam9919
    @akam9919 5 месяцев назад

    I'm sorry, but I don't care about performance enough to have to 1) write an extension to a LANGUAGE I AM NOT WRITING IN and 2) WTF AM I WRITING FILE EXTENSIONS ANYWAY? Seriously, how much of a performance decrease is automatically figuring out what file I'm talking about?!

    • @mattpocockuk
      @mattpocockuk  5 месяцев назад

      Honestly, it can be pretty bad for serverless functions. Any call to the filesystem is extremely expensive performance-wise.

  • @SergiySev
    @SergiySev 8 месяцев назад +1

    javascript is broken...

  • @shoe3
    @shoe3 8 месяцев назад

    Seems unnecessarily harmful to the developer experience

  • @mattiarasulo9934
    @mattiarasulo9934 8 месяцев назад

    I LOVE Javascript but its module system is the most dumb thing I’ve ever seen in any cose system..