parcel icon indicating copy to clipboard operation
parcel copied to clipboard

Parcel does not generate types when using targets

Open EnKrypt opened this issue 2 years ago • 9 comments

🐛 bug report

I am building a library with Typescript. I have targets defined in package.json. When running parcel build with --target <name>, it ignores the types entry in package.json and does not generate a .d.ts file.

🎛 Configuration (package.json, cli command)

{
  "name": "some-name",
  "version": "1.0.0",
  "license": "UNLICENSED",
  "engines": {
    "node": ">= 14"
  },
  "targets": {
    "static": {
      "isLibrary": true,
      "distDir": "../static"
    },
    "publish": {
      "isLibrary": true,
      "distDir": "./dist"
    }
  },
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "files": ["dist"],
  "scripts": {
    "dev": "parcel watch src/index.tsx --watch-for-stdin",
    "build": "rm -rf dist && tsc --noEmit && parcel build --no-cache src/index.tsx --reporter @parcel/reporter-bundle-analyzer",
    "test": "tsc --noEmit",
    "prepublishOnly": "npm run build -- --target publish",
    "lint": "eslint . --ext js,jsx,ts,tsx"
  },
  "devDependencies": {
    "@parcel/config-default": "^2.5.0",
    "@parcel/packager-ts": "2.5.0",
    "@parcel/reporter-bundle-analyzer": "^2.5.0",
    "@parcel/transformer-typescript-types": "2.5.0",
    "@types/react": "^18.0.8",
    "@types/react-dom": "^18.0.3",
    "@typescript-eslint/eslint-plugin": "^5.22.0",
    "@typescript-eslint/parser": "^5.22.0",
    "eslint": "^8.14.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-prettier": "^4.0.0",
    "eslint-plugin-react": "^7.28.0",
    "eslint-plugin-react-hooks": "^4.3.0",
    "parcel": "^2.5.0",
    "parcel-transformer-css-to-string": "^0.9.1",
    "postcss": "^8.4.13",
    "prettier": "^2.6.2",
    "react": "^18.1.0",
    "react-dom": "^18.1.0",
    "tailwindcss": "^3.0.24",
    "typescript": "^4.6.4"
  },
  "peerDependencies": {
    "react": "16.9.0 - 18",
    "react-dom": "16.9.0 - 18"
  }
}

🤔 Expected Behavior

I am running:

parcel build --no-cache src/index.tsx --target static

But Parcel only generates index.js. I also expected it to generate index.d.ts which it is not doing.

😯 Current Behavior

No index.d.ts file generated

💁 Possible Solution

No clue, I'm hoping I'm just missing some configuration and this will be an easy fix.

🔦 Context

I need to run Parcel in watch mode as well. So while I could build without --target and copy the types manually, it doesn't work for watch mode and is very inconvenient to build multiple times just for types as a hack. I'm hoping there is a cleaner, more intentional solution for this situation.

🌍 Your Environment

Software Version(s)
Parcel 2.5.0
Node 16.15.0
npm 8.5.5
Operating System Linux

EnKrypt avatar May 11 '22 07:05 EnKrypt

The "pkg#types" mechanism is implemented internally as just an additional target. So if you override which targets run by setting --target static, you'll need to add --target types as well.

mischnic avatar May 11 '22 07:05 mischnic

This does not let me specify the context with which types are built, as this context differs per target. See: https://github.com/parcel-bundler/parcel/discussions/7379

For me specifically, the context of which directory to generate the output is something I need to configure.

Is such a configuration currently possible?

EnKrypt avatar May 11 '22 10:05 EnKrypt

I'm seeing something more. Even when I am generating all targets, I still see no type declaration files...

starpit avatar May 13 '22 16:05 starpit

types is a target just like main or module.

If what you're asking for is a way to have multiple such targets: no, that's currently not possible. It has to be called "types", so there can only be one.

mischnic avatar May 13 '22 16:05 mischnic

thanks for the help! with this, i get no .d.ts files in dist/. without the targets spec, i do get a types.d.ts file. this is why i assumed it was related to having targets, hence the post here. 🙇

  "main": "dist/api/api.js",
  "type": "module",
  "types": "dist/api/types.d.ts",
  "targets": {
    "cli": {
      "context": "node",
      "isLibrary": true,
      "outputFormat": "esmodule",
      "source": "src/index.ts"
    },
    "api": {
      "context": "node",
      "isLibrary": true,
      "outputFormat": "esmodule",
      "source": "src/api.ts"
    }
  },

starpit avatar May 13 '22 16:05 starpit

If what you're asking for is a way to have multiple such targets: no, that's currently not possible. It has to be called "types", so there can only be one.

That's unfortunate. Any idea if it could be a planned feature for specifying types per build? I'd be happy to leave this issue open as a pitch to consider adding it in the future if there are others who feel the same.

EnKrypt avatar May 17 '22 12:05 EnKrypt

What is the status here? I really need to have two targets with different type definition files for each bundle result.

viniciuspalma avatar Aug 31 '22 16:08 viniciuspalma

@viniciuspalma As a workaround, I ended up using tsc to manually generate types the way I wanted, and then moving it around. I have a feeling this isn't going to be addressed by parcel soon.

EnKrypt avatar Sep 06 '22 11:09 EnKrypt

No matter what I try, I cannot get types to output if I have any targets defined in my package.json.

edit

I got it to work. I don't know if this is a feature or a bug, but I'm going to call it a bug. I'm not really sure what exactly is going on, but it has to do with exclusiveTargets and skipTarget preventing main and types from building. To get around this, I add two empty targets, main and types:

{
  "source": "src/index.ts",
  "main": "dist/index.js",
  "types": "dist/types.d.ts",
  "targets": {
    "main": {},
    "types": {},
    "preview": {
      "source": "src/index.html",
      "distDir": "preview",
      "isLibrary": false
    }
  },
}

And now Parcel correctly bundles the preview target and the main/types targets.

kkirby avatar Sep 06 '22 17:09 kkirby

Awesome @kkirby 💯

ng-hai avatar Sep 30 '22 10:09 ng-hai