Search code examples
node.jstypescriptexpressheroku

Heroku build can't find `@types` in package.json file


Heroku Build Error

- TSError: ⨯ Unable to compile TypeScript:
- src/server.ts(1,38): error TS7016: Could not find a declaration file for module 'express'. '/app/node_modules/express/index.js' implicitly has an 'any' type.
- Try `npm i --save-dev @types/express` if it exists or add a new declaration (.d.ts) file containing `declare module 'express';`
- src/server.ts(10,14): error TS2580: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.

Been getting held up for a while trying to figure out how to get my code up to heroku, the latest error is shown above and I'm not sure what I need to change to get it working. I've been following guides and have a @types/express, @types/node, etc. in my package.json script. However, it's not reading them. Not sure where to go from here, help would be appreciated.

tsconfig.json

{
  "compilerOptions": {
    "target": "es2017",
    "module": "commonjs",
    "sourceMap": true,
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "noImplicitAny": true,
    "moduleResolution": "node",
    "baseUrl": "./src",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "lib": ["es2015"],
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "src/**/*.test.ts"]
}

Procfile

web:ts-node/src/server.ts 

src/server.ts

import express, { Application } from 'express';
import { routes } from './routes';

// Boot express
export const app: Application = express();

// Application routing
routes(app);

const port = process.env.PORT || 5000;

// Start server
app.listen(port, () => console.log(`Server is listening on port ${port}!`));

package.json

{
  "name": "my-app",
  "version": "1.0.0",
  "main": "src/server.ts",
  "type": "commonjs",
  "scripts": {
    "start": "ts-node src/server.ts",
    "dev": "nodemon -x ts-node src/server.ts",
    "build": "tsc",
    "test": "jest --coverage"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "husky": {
    "hooks": {
      "pre-commit": "pretty-quick --staged"
    }
  },
  "devDependencies": {
    "@types/cors": "^2.8.12",
    "@types/express": "^4.17.13",
    "@types/node": "^16.7.6",
    "@types/jest": "^26.0.24",
    "@types/supertest": "^2.0.11",
    "@typescript-eslint/eslint-plugin": "^4.29.0",
    "@typescript-eslint/parser": "^4.29.0",
    "eslint": "^7.32.0",
    "eslint-config-standard": "^16.0.3",
    "eslint-plugin-import": "^2.23.4",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-promise": "^5.1.0",
    "husky": "^7.0.1",
    "jest": "^27.0.6",
    "nodemon": "^2.0.12",
    "prettier": "^2.3.2",
    "pretty-quick": "^3.1.1",
    "supertest": "^6.1.4",
    "ts-jest": "^27.0.4"
  },
  "dependencies": {
    "axios": "^0.21.1",
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "ts-node": "^10.1.0",
    "typescript": "^4.3.5"
  },
  "description": ""
}


Solution

  • Figured it out.

    Heroku prunes dev dependencies when it builds your project. Since all my @types were located in devDependencies they weren't reachable and resulted in the error shown in the initial post.

    package.json

      // i also added engine specifications. 
      // the docs suggest matching your configurations as closely to your dev 
      // environment as possible for obvious reasons.  
      "engines": {
        "node": "15.x",
        "npm": "7.x"
      },
    ...
      "dependencies": {
        "@types/cors": "^2.8.12",
        "@types/express": "^4.17.13",
        "@types/node": "^16.7.6",
        "axios": "^0.21.1",
        "body-parser": "^1.19.0",
        "cors": "^2.8.5",
        "express": "^4.17.1",
        "ts-node": "^10.2.1",
        "typescript": "^4.4.2"
      }