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"]
}```
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With