Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use enum from typescript definition file?

I'm programming in nodejs using typescript.

I'm using pdfmake and I installed typescript definition files for this library (@types/pdfmake)

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/pdfmake/index.d.ts

I'm importing one of the enums from this file

import { PageSize } from "pdfmake/build/pdfmake";

and using it like this PageSize.A4

This compiles, but when I try to access value A4 of this enum, runtime error occurs

TypeError: Cannot read property 'A4' of undefined

Any help would be greatly appreciated

package.json:

{
  "name": "nodejs-pdf-make",
  "version": "1.0.0",
  "description": "",
  "main": "dist/app.js",
  "scripts": {
    "start": "tsc && node --inspect dist/app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/express": "^4.17.1",
    "tslint": "^5.19.0",
    "typescript": "^3.6.2"
  },
  "dependencies": {
    "@types/pdfmake": "^0.1.8",
    "express": "^4.17.1",
    "pdfmake": "^0.1.58"
  }
}

tsconfig.json:

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "target": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist"
  },
  "lib": ["es2015"]
}```
like image 855
displayName Avatar asked Sep 03 '19 14:09

displayName


People also ask

How do I use enum values in TypeScript?

In TypeScript, enums, or enumerated types, are data structures of constant length that hold a set of constant values. Each of these constant values is known as a member of the enum. Enums are useful when setting properties or values that can only be a certain number of possible values.

Can I export a enum in TypeScript?

TypeScript uses the concept of modules, in the same way that JavaScript does. In order to be able to import an enum from a different file, it has to be exported using a named or default export.

Should I use enums in TypeScript?

Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript. Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases. TypeScript provides both numeric and string-based enums.

How do I convert a string to enum in TypeScript?

To convert a string to an enum: Use keyof typeof to cast the string to the type of the enum. Use bracket notation to access the corresponding value of the string in the enum.


2 Answers

When processing an enum in a TypeScript source file (.ts), the TypeScript compiler emits the appropriate JavaScript code to create an object which can be accessed at runtime.

However when processing the TypeScript declaration file (.d.ts) in your case, the enum is has been wrapped inside a declare module "pdfmake/build/pdfmake" block. Inside a "declare module", the compiler does not try to implement the object. Compare example 1 vsexample 2 on the TypeScript playground to understand the effect.

This behavior is by design, because the intended use-case for declaration files is enable type-checking of code written in a separate module (typically one written in JavaScript.)

Let me know if that isn't clear.

like image 147
Burt_Harris Avatar answered Oct 30 '22 13:10

Burt_Harris


The problem is that type definitions are just for types. They don't change the runtime behavior of a module. So while TypeScript is happy with your code because the type definitions say that this module exports an enum PageSize, this falls apart when running the code because in reality the module does not export PageSize.

I would consider this a bug in @types/pdfmake.

This problem could be resolved in @types/pdfmake by making the enum const:

const enum PageSize {
   // ...
}

TypeScript automatically inlines const enums. Inlining means the compiler replaces PageSize.A4 with 'A4' so that there are no references to PageSize left in the JavaScript code.

Of course this would require a change in @types/pdfmake. I encourage you to open a pull request or issue on the DefinitelyTyped repo.


Without any changes in @types/pdfmake the only option you have is use hardcoded strings:

pageSize: 'A4' as PageSize

Unfortunately you'll probably even have to cast it to the PageSize enum, because that's what the type definitions expect.

like image 33
lukasgeiter Avatar answered Oct 30 '22 14:10

lukasgeiter