Home > Enterprise >  Why Aren't TypeScript Enum Keys Being Transpiled?
Why Aren't TypeScript Enum Keys Being Transpiled?

Time:07-31

I've set up a project with TypeScript, Webpack, Babel, and React, but i'm running into some trouble with using enum members as keys for an object.

The file in question looks like this:

// traits.ts
import { Trait } from "models/abilities";

const traits: { [key in TraitName]: Trait } = {
  [TraitName.Combat]: new Trait({
    aspect: Aspect.Power,
    name: TraitName.Combat
    }),
    ...
}

The object TraitName is an enum created in a global .d.ts file:

/// global.d.ts

enum TraitName {
  Combat = "Combat",
  ...
}

This all works fine for the build. It all compiles successfully in Webpack and TypeScript doesn't complain. However, when I load up my browser, I get this error: "Reference Error: TraitName is not defined"

Checking the code in the dev console, it appears everything transpiled fine except the enum. It is still represented as if it is an object in the file/imported into the file, but it isn't being imported.

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var models_abilities__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! models/abilities */ "./src/models/abilities/index.ts");

const traits = {
  /* It starts complaining here */ [TraitName.Combat]: new models_abilities__WEBPACK_IMPORTED_MODULE_0__.Trait({
    aspect: Aspect.Power,
    name: TraitName.Combat,
    ...

Should those enum references not be replaced with their values during transpilation? I don't know if maybe I have something configured wrong, but I'd appreciate some insight.

TS Config:

{
  "compilerOptions": {
    "target": "es6",
    "outDir": "./build",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "react-jsx",
    "baseUrl": ".",
    "paths": {
      "data/*": [
        "src/data/*"
      ],
      "models/*": [
        "src/models/*"
      ],
      "presentation/*": [
        "src/presentation/*"
      ],
      "services/*": [
        "src/services/*"
      ],
      "utils": [
        "src/utils"
      ]
    }
  },
  "include": [
    "src"
  ]
}

Webpack Config:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const ESLintPlugin = require("eslint-webpack-plugin");

module.exports = {
  entry: path.join(__dirname, "src", "index.tsx"),
  output: {
    path: path.join(__dirname, "build"),
    filename: "[name].[contenthash].bundle.js"
  },
  mode: process.env.NODE_ENV || "development",
  resolve: {
    extensions: [".ts", ".tsx", ".js", ".jsx"],
    plugins: [new TsconfigPathsPlugin({ extensions: [".ts", ".tsx", ".js", ".jsx"] })]
  },
  devServer: {
    port: 3000,
    liveReload: false,
    hot: true
  },
  module: {
    rules: [
      {
        test: /\.js(x)?$/,
        exclude: /node_modules|__tests__/,
        use: ["babel-loader"]
      },
      {
        test: /\.ts(x)?$/,
        exclude: /node_modules|__tests__/,
        use: ["babel-loader"]
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: ["style-loader", "css-loader"]
      }
    ],
  },
  stats: {
    assets: false,
    builtAt: false,
    moduleAssets: false,
    cachedModules: false,
    runtimeModules: false,
    cachedAssets: false,
    children: false,
    chunks: false,
    context: path.resolve(__dirname, "src"),
    errors: true,
    hash: false,
    logging: "warn",
    modules: false,
    timings: false,
    version: false,
    warnings: true
  },
  plugins: [
    new ESLintPlugin({
      context: "./src",
      extensions: ["ts", "tsx"]
    }),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "src", "index.html"),
    }),
  ],
};

.babelrc

{
  "presets": [
      "@babel/env",
      "@babel/react",
      "@babel/preset-typescript"
  ],
  "plugins": [
    "@babel/plugin-proposal-class-properties"
  ]
}

NOTE: I was loading typescript with ts-loader, but that produced the same result and I'm seeing documentation that simply uses babel to load it. Not really sure which I should be doing, but changing that doesn't fix this problem.

CodePudding user response:

Files with .d.ts extension are not transpiled.

In your case, you could probably just rename it with .ts extension.

  • Related