Skip to content

ts-node tries to compile any imported file as Typescript (and fails when it's not) #175

Description

@JabX

I am trying to setup some tests with ts-node and tape for my React components, but I am encountering some imports like import 'style.css'; which are meant to be processed by Webpack and ignored by Typescript. The problem is that ts-node attempts to parse it as Typescript and then (obviously) fails.

Is there something we can do here so solve this?

Activity

  1. blakeembrey commented on Aug 17, 2016

    @blakeembrey
    Member

    This is not ts-node, this is just how node works. There isn't any way to do what you want in node except to use conditional requires.

  2. added
    questionSupport requests. We tend not to answer these on Github. Nowadays I convert to Discussion instead.
    on Aug 17, 2016
  3. JabX commented on Aug 18, 2016

    @JabX
    Author

    Okay, thanks for the tip. I suppose I should use something like this then?

  4. blakeembrey commented on Aug 19, 2016

    @blakeembrey
    Member

    @JabX That looks like it could work. By default, any require will be execute by node and that's exactly (educated guess) what's happening here. You'd be running into a runtime error, not because of TypeScript, but because node is trying to evaluate your CSS and JavaScript.

  5. onlywei commented on Jan 17, 2019

    @onlywei

    I apologize for resurrecting this thread more than two years after its closing, but CSS file imports remain the primary reason why I have to resort to using Webpack on the server-side instead of being able to use ts-node.

    My understanding is that a statement like import 'style.css'; will be converted by TypeScript to require('style.css');. I am hoping for a way in my tsconfig.json to specify that import 'style.css'; should be converted into a blank empty line instead.

  6. blakeembrey commented on Jan 18, 2019

    @blakeembrey
    Member

    @onlywei That's out of scope for this module though, I'm sure there's projects well defined for this sort of things (it's really just doing require.extensions['.css'] = () => undefined).

  7. DanKaplanSES commented on Jan 26, 2025

    @DanKaplanSES

    There isn't any way to do what you want in node except to use conditional requires.

    If you are using ESM modules (i.e., import) here's an example of doing that:

    export {};
    
    (async function () {
      // eslint-disable-next-line no-constant-condition
      if (false) {
        await import('style.css');
      }
    })().catch((reason) => {
      console.error(reason);
    });
    

    Since the import is wrapped in an if (false), it will never execute in ts-node/node. That means no error at runtime. But here's the thing...

    My bundler (rollup) is smart enough to know that too. As a result, this code is removed during tree-shaking. And as a result of that, this CSS file isn't added to my bundle.

    I'm importing this CSS file because I want it in my bundle, so if the conditional import removes it, I'm right back where I started. To put it another way, I need node to ignore this import and I need my bundler to recognize it.1

    Without ts-node, this is relatively straightforward because you transpile and execute code as separate steps. Typescript ignores CSS imports out-of-the-box2, and after installing the appropriate rollup plugin, it bundles imported css files after a one line change to your config file.

    I'm unclear on how to do the same with ts-node. Above, @blakeembrey said, "This is not ts-node, this is just how node works," which is true. If I were to pass the output of tsc directly into node, I would get the same error ts-node gives me. As I mentioned earlier, I would need to postprocess the javascript before it's executed by node. But as far as I can tell, ts-node doesn't give me a way to do this because it transpiles and executes in the same step. If my understanding is correct, that means ts-node always errors if you use a typescript css import.

    After lots of trial and error, I've run out of ideas and it feels like I have to pick one of these two options:

    1. Stop using ts-node
    2. Stop using typescript css imports.

    I'm hoping there's a solution I haven't thought of that allows me to use both.

    Footnotes

    1. It would probably help to add additional context to my use case. I want my unit tests to run as fast as possible. ts-node allows me to skip the type checking and transpilation stage, giving me faster feedback loops.

      It's worked without issue until I noticed my bundle was missing css files from a dependency. I found what I considered to be the best way to solve this via typescript (i.e., css imports), but I ran into the problem I've described above. My unit tests no longer execute because they try to parse the css file as though it were javascript.

      Keep in mind, I still need to type check and transpile my project at the end of my build pipeline: It's a client side app that runs in the browser. ↩

    2. See https://devblogs.microsoft.com/typescript/announcing-typescript-5-6/#the---nouncheckedsideeffectimports-option

      In TypeScript, this syntax has had a pretty strange quirk: if the import could be resolved to a valid source file, then TypeScript would load and check the file. On the other hand, if no source file could be found, TypeScript would silently ignore the import!

      ↩
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    invalidquestionSupport requests. We tend not to answer these on Github. Nowadays I convert to Discussion instead.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions