Generating TypeScript typings in parcel for scss

Viewed 618

From what I gather in the documentation, this can be done with very little configuration and without a tsconfig.json.

The issue I'm trying to resolve is: Cannot find module './styles.module.scss' or its corresponding type declarations. ts(2307)

enter image description here

This is my project structure:

enter image description here

What I've tried to do:

  • Install npm i @types/scss-parser --save-dev

  • Generating Types:

    {
       ...
         "source": "src/index.ts",
         "module": "dist/index.js",
         "types": "dist/index.d.ts",
       ...
    }
    

    But that just gives me: Error: No transformers found for src/index.html with pipeline: 'types'.

    Removing types: then results in the error: @parcel/namer-default: Target "module" declares an output file path of "dist/index.js" which does not match the compiled bundle type "html".

    Changing to "module": "dist/index.html" results in: @parcel/core: Unexpected output file type .html in target "module"... File extension must be .js or .mjs"

I'm not sure how to resolve the issue then and have a feeling will actually have to make a tsconfig.json or a types declaration of some kind.

I just wanted to check here before doing that to see if there is a way to resolve this without making additional files. Any suggestions?

1 Answers

Unfortunately, I don't think there's an out-of-the-box way for parcel to generate the necessary .d.ts files to provide strong typing for .scss modules. The Generating Types documentation you linked to above describes how people who author libraries (e.g. npm packages that are published and consumed by others) can use parcel to generate a consolidated .d.ts file that describes .js bundle generated by parcel, which doesn't sound like your use case.

Fortunately, there is a great tool called typed-scss-modules that can generate .d.ts files that describe all .module.scss files in your project, and it's pretty simple to integrate it into a parcel-based project. Here's what you need to do:

  1. Install typed-scss-modules:
     yarn add -D typed-scss-modules
    
  2. Add a command to your package.json that will generate the .d.ts files for all .module.scss files in your project:
    "build:scss-types": "tsm src --nameFormat none --exportType default",
    
    By default, typed-scss-modules will transform the names of the classes defined in .scss files to camel case, and remove dashes. This is not the way parcel behaves (it will leave class names untouched). But you can align with parcel behavior using the --nameFormat none option.
  3. Then, you can import class names into your typescript files like this:
    import classes from "./styles.module.scss";
    
    (Note how this uses the default export, not import * from syntax - this aligns with the --exportType default option above).
  4. Now VSCode, tsc and @parcel/validator-typescript should be happy. You'll get Intellisense, and errors if you ever make a typo referencing a name from the classes import.
  5. For the best workflow, you might consider adding the build:scss-types command to your build and CI pipeline so that you'll get build-time errors if you ever make a naming mistake. You can also run tsm with the --watch option to re-generate .d.ts files automatically during devlopment.

Here is a repo where this is all working that you can use as an example.

Related