Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I have an enum in my Typescript / Ember 3.1 app and I am getting import errors at runtime. What's going on?

I have an ember component that is importing an enum type as follows:

import { StateNames, CardSummary } from '../../types/snowcat/state-types'

the type file is as follows:

export enum CardState {
  error = 'error',
  new = 'new',
  okay = 'okay',
  warning = 'warning',
}

I'm then using the enum as follows in the component:

  @computed('cardSummary.cardState')
  get type(): string {
    if ([CardState.new, CardState.okay, CardState.warning].includes(this.cardSummary.cardState)) {
      return 'info'
    }
    return 'error'
  }

Everything seems fine with the code. I am not getting any TypeScript errors when the code builds, but I am getting a runtime error:

loader.js:247 Uncaught Error: Could not find module `types/snowcat/state-types` imported from `snowcat/models/certificate`
    at missingModule (loader.js:247)
    at findModule (loader.js:258)
    at Module.findDeps (loader.js:168)
    at findModule (loader.js:262)
    at requireModule (loader.js:24)
    at r (loader.js:176)
    at ember-data.js:39
    at Array.forEach (<anonymous>)
    at getDsModels (ember-data.js:36)
    at getModels (ember-data.js:66)

What's going on? How do I fix this?

like image 449
pbanka Avatar asked Mar 28 '18 21:03

pbanka


1 Answers

This is because the types module is not included for compilation by ember-cli-typescript. Pure type declarations will work fine, because they're erased at compile-time. However, enums have runtime representations, not just compile-time representations—unlike pretty much everything else in TypeScript! (You can sometimes work around that with const enum types instead, but they have their own tradeoffs.)

In any case, because ember-cli-typescript doesn't by default include the types directory for compilation—only for type resolution—the result is that you could use the enums as a type but you couldn't use them to actually create a value from them, which mostly defeats the point.

The best move is to keep your-app/types/ for things which are just declaring types that exist outside your app, or common types with no runtime representation in your app, and to put types which have runtime functionality associated with them in something like your-app/app/lib. You can then export the types from whatever modules and reuse them throughout your application just like normal.

Alternatively, you can add types to the tsconfig.json's "paths" list, but that might be surprising to other users of ember-cli-typescript who start working on your app!

like image 131
Chris Krycho Avatar answered Nov 17 '22 13:11

Chris Krycho