Hi,
I'm trying to move from webpack to rollup for a library and I have trouble getting declarations to work correctly.
It seems that interfaces declarations aren't exported, this is a problem when I have things like :
import { RenderedCell } from "../RenderedCell";
export default class MergedCell implements RenderedCell {
// ...
}
I get the error that RenderedCell can't be found.
I worked in webpack, and I can't understand what's the difference in my configuration that broke this. but I seem to understand that it's normal with Rollup.
BTW. I'm using the latest rollup, rollup-plugin-typescript2 and rollup-plugin-uglify I can post my configurations if needed
Is this a runtime error, or typescript error? Could you post how you export the interface from RenderedCell
itself?
The thing is that the file isn't generated at all, and it fails when using the library in another project.
Wait, are you expecting RenderedCell
interface to be generated? From the code you posted typescript would expect file named RenderedCell.ts
to exist one directory above current file and it would need to contain something like this:
export interface RenderedCell
{
// ...
}
Could you give more details on your project structure? (file tree, tsconfig, rollup config, etc)
yes I'm expecting it to be generated.
Here are my configurations :
running the build : rollup -c -f es -n sq-web-component-table -o dist/sq-web-component-table.es.min.js
I didn't put the whole tree because it's a quite big library and it's more noise than signal. But you can already see that many files aren't generated in the dist.
rollup.config.ts
import typescript from 'rollup-plugin-typescript2';
import uglify from 'rollup-plugin-uglify';
import { minify } from 'uglify-es';
export default {
entry: './src/index.ts',
dest: 'dist/sq-web-component-table.min.js',
sourceMap: true,
plugins: [
typescript(),
uglify({}, minify)
]
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"declaration": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"outDir": "dist"
},
"include": [
"src/**/*.ts"
],
"exclude": [
"dist",
"node_modules",
"**/*-test.ts"
]
}
RenderedCell.ts
import {RenderedElement} from "./RenderedElement";
import {RenderedRow} from "./RenderedRow";
export interface RenderedCell extends RenderedElement {
isMergedCell(): boolean;
getColspan(): number;
setColspan(colspan: number): void;
getParent(): RenderedRow;
}
File tree
.
βββ src
βΒ Β βββ index.ts
βΒ Β βββ table
βΒ Β βββ extensions
βΒ Β βΒ Β βββ base
βΒ Β βΒ Β βΒ Β βββ FirstTableExtension.ts
βΒ Β βΒ Β βΒ Β βββ LastTableExtension.ts
βΒ Β βΒ Β βΒ Β βββ SectionDispatcher.ts
βΒ Β βΒ Β βΒ Β βββ SectionManager.ts
βΒ Β βΒ Β βΒ Β βββ SizeChangeMonitor.ts
βΒ Β βΒ Β βββ InvalidateEvent.ts
βΒ Β βΒ Β βββ InvalidateSizesEvent.ts
βΒ Β βΒ Β βββ RenderedCell.ts
βΒ Β βΒ Β βββ RenderedElement.ts
βΒ Β βΒ Β βββ RenderedRow.ts
βΒ Β βΒ Β βββ RenderedSection.ts
βΒ Β βΒ Β βββ RenderedTable.ts
βΒ Β βΒ Β βββ SectionClickedEvent.ts
βΒ Β βΒ Β βββ support
βΒ Β βΒ Β βΒ Β βββ ...
βΒ Β βΒ Β βββ TableAttributes.ts
βΒ Β βΒ Β βββ TableExtensionChain.ts
βΒ Β βΒ Β βββ TableExtensionList.ts
βΒ Β βΒ Β βββ TableExtension.ts
βΒ Β βββ model
βΒ Β βΒ Β βββ ...
βΒ Β βββ TableRenderingOptions.ts
βΒ Β βββ Table.ts
βΒ Β βββ util
βΒ Β βΒ Β βββ ...
βΒ Β βββ view
βΒ Β βββ ...
βββ dist
βΒ Β βββ index.d.ts
βΒ Β βββ sq-web-component-table.es.min.js
βΒ Β βββ sq-web-component-table.es.min.js.map
βΒ Β βββ sq-web-component-table.min.js
βΒ Β βββ sq-web-component-table.min.js.map
βΒ Β βββ table
βΒ Β βββ extensions
βΒ Β βΒ Β βββ base
βΒ Β βΒ Β βΒ Β βββ FirstTableExtension.d.ts
βΒ Β βΒ Β βΒ Β βββ LastTableExtension.d.ts
βΒ Β βΒ Β βΒ Β βββ SectionDispatcher.d.ts
βΒ Β βΒ Β βΒ Β βββ SectionManager.d.ts
βΒ Β βΒ Β βΒ Β βββ SizeChangeMonitor.d.ts
βΒ Β βΒ Β βββ InvalidateEvent.d.ts
βΒ Β βΒ Β βββ InvalidateSizesEvent.d.ts
βΒ Β βΒ Β βββ RenderedRow.d.ts
βΒ Β βΒ Β βββ SectionClickedEvent.d.ts
βΒ Β βΒ Β βββ support
βΒ Β βΒ Β βΒ Β βββ ...
βΒ Β βΒ Β βββ TableAttributes.d.ts
βΒ Β βΒ Β βββ TableExtensionList.d.ts
βΒ Β βββ model
βΒ Β βΒ Β βββ ...
βΒ Β βββ Table.d.ts
βΒ Β βββ util
βΒ Β βΒ Β βββ ...
βΒ Β βββ view
βΒ Β βββ ...
βββ node_modules
βΒ Β βββ ...
βββ __tests__
βΒ Β βββ ...
βββ package.json
βββ rollup.config.js
βββ tsconfig.json
Ah, I see. Is the lib opensource by any chance?
Try building with those options:
typescript({ verbosity: 2, clean: true }),
Check if all files you expect are being processed. If declarations suddenly start being generated then there is a cache problem somewhere.
If RenderedCell.ts is not mentioned in output (rpt2: transpiling '...'
), increase verbosity to 3 and check if files that are supposed to import it are doing that. You should see something like
rpt2: resolving '../RenderedCell'
rpt2: to '...'
If the problem is not obvious then, I'll add more logging somewhere.
I would love to, might be in the future :)
Thanks for the tricks, I will try this on monday.
If you set declaration: false
in the compilerOptions section of your tsconfig and recompile, does the issue go away? If yes, is the error reported by TSC related to one of the files within the dist directory? If yes is your answer to both, does the error go away if you introduce some non-type logic to the file containing RenderedCell
file such as an export of a simple function? If yes, then the reason is that the file containing RenderedCell
is considered unused and Typescript won't ever prepare declarations for it.
If all of this applies to you, I see 2 options:
Hi,
sorry for the long delay, I tried your tips and tricks but I still couldn't get the type definitions for interfaces generated.
I changed the configuration to typescript({ verbosity: 3, clean: true })
.
In the output of the generated build there is not a single mention of the RenderedCell
interface.
I'm 100% sure this file is needed, as the index.d.ts
of the library directly requires it and all files but the interfaces are generated, but the interfaces are still in the imports of the index.d.ts
file.
I will dive in the code to see if there is a particular reason why those files aren't generated.
@wessberg Stop generating declarations for my bundle is not an option as this is a library that is part of a bigger project all written in TypeScript, so if it doesn't have typings it doesn't work.
So, I made some investigation and created a repository that reproduces my case with a minimal set of configuration : https://github.com/onigoetz/typescript-rollup-experiment
I also included a webpack configuration to compare how webpack makes it work.
My understanding of the problem is that when rollup-plugin-typescript2 requires the compiled version of a file (let's say index.ts) Typescript will return the compiled files and it's imports, but without the interfaces in the imports.
That's why rollup never generates them : it's not aware of their existence.
To run the repository do an npm install && npm run build
inside the directory.
If you add:
import "./SomeInterface";
(exactly like that, - without any named bindings) to your index.ts
file, it should work. Does it?
Unfortunately, Rollup doesn't invoke the transform handler of plugins for declaration-only files such as files containing only type declarations. The thing above should work since that forces Rollup to evaluate the file. This issue: https://github.com/rollup/rollup-plugin-typescript/issues/28 explains how and why this issue exists. Theoretically, we could manually resolve all dependencies of your application from the entry point and determine those that only contain type declarations, but there is no way of forcing rollup to invoke the transform hook (beside other obvious downsides such as much added build-step complexity).
I'm afraid we can't do much about this without altering rollup itself. The "hack" I described should work for now though.
Yep, just checked, adding import "./SomeInterface";
in the test repo fixes things.
When importing types only, typescript elides import statements from js output and rollup doesn't see those files and thus doesn't send them for transpiling.
I'll try to cheat and monitor which files typescript requested from disk vs which files rollup sent for transpiling. Should be possible to force-transpile the difference with definitions only flag. This might result in too many d.ts files in some cases I though (for things rollup has legitimately shaken from the tree for example)
Thanks for looking into it, I will also check if I can make a contribution for this.
@onigoetz, ok, try your project with master. Check if right declarations are generated, but also check that no unexpected ones are :)
Awesome, you litteraly fixed it while I was sleeping :)
I tested it and it almost works fine.
There is just a small issue, but I think it's something we can't do anything against, the webpack loader does exactly the same and the file list is generated by TypeScript itself.
As an example; If I have three files in my repo :
index.ts
importing SomeInterface.ts
SomeInterface.ts
nongenerated.ts
importing SomeInterface.ts
nongenerated.ts
is never referenced but its types are generated anyway.
Cool, thanks for testing. I'll release it a bit later after another issue is confirmed.
Yeah not much we can do when bypassing rollup. You should be able to exclude those files manually in exclude
option, but that's a poor workaround.
Ok, in 0.5.1 now
work well ,just config tsconfig.json
{
"compilerOptions": {
"module": "es2015",
"target": "es5",
"declaration":true,
"declarationDir": "lib",
"typeRoots": [
"node_modules/@six006",
"node_modules/@types"
],
"lib": [
"es2015",
"es2017",
"es5"
],
},
"include": [
"src/index.ts",
"src/module/**/*.ts"
],
"exclude": [
"node_modules"
]
}
include
section tell you what to generate
YMMV but I got it to work like this ...
before
export type MyType = { ... };
after
type MyType = { ... };
export { MyType }
For what it's worth, I just call tsc --emitDeclarationOnly
after rollup, which overrides the declaration files into build folder.
in my package.json
"scripts": {
"build": "rollup -c",
"postbuild: "tsc --emitDeclarationOnly"
}
Most helpful comment
For what it's worth, I just call
tsc --emitDeclarationOnly
after rollup, which overrides the declaration files into build folder.in my package.json