ivogabe / gulp-typescript

A TypeScript compiler for gulp with incremental compilation support.
MIT License
839 stars 129 forks source link

Option to *only* emit declarations, no JavaScript #607

Closed ELLIOTTCABLE closed 4 years ago

ELLIOTTCABLE commented 5 years ago

Expected behavior: I'm able to consume only the .dts stream of a gulp-typescript stream.

Actual behavior: I have to manually close the unused .js stream, if I only want the definitions.

Your gulpfile:

  const stream = gulp.src(inputs, { matchBase: true })
    .pipe(sourcemaps.init({ loadMaps: true }));

  if (!usingTypescript) {
    return stream
      .pipe(babel())
      .pipe(sourcemaps.write('.'))
      .pipe(gulp.dest(destinationFolder));

  } else {
    let gulpTypescript;
    try {
      gulpTypescript = require('gulp-typescript');
    } catch (e) {
      throw new PluginError('@codeverse/gulp-registry',
        'The TypeScript peer-dependency is missing, and `tsx?` is present in' +
        '\n    `transpileGlobs`. Either add the former, or remove the latter.');
    }

    const typedStream = stream
      .pipe(filter('**/*.{ts,tsx}'))
      .pipe(gulpTypescript.createProject('tsconfig.json', {
        declaration: true
      })());

    // Horrible hack, this time to discard the emitted JavaScript output
    typedStream.js.emit('end');

    return merge(
      typedStream.dts
        .pipe(gulp.dest(destinationFolder)),
      stream
        .pipe(babel())
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest(destinationFolder))
    );

Basically, I think we need the inverse of the declarations: option — an equivalent of tsc's --emitDeclarationOnly. (My personal use-case is that we have a set of separate, complicated build-systems; and we'd like to standardize on a single source-of-truth regarding as much configuration as possible. I'm trying to make sure that Babel is responsible for all JavaScript output, including stripping TypeScript extensions; I only want to use the TypeScript compiler as a static type-checker, and to publish typing information to npm. Hence gulp-typescript.)

ivogabe commented 5 years ago

That's strange, I would have expected that to just work. Especially since it works fine the other way around, if you only consume the .js stream. What happens without your hack? Does the stream pass all files but never closes, or does it not pass any files at all? Does merge have an influence on this, eg could you try to only return the definitions stream?

ELLIOTTCABLE commented 5 years ago

Unfortunately, I've lost access to the code in which I added this behaviour.

If you're unable to reproduce personally, feel free to close!

andsouto commented 5 years ago

I am working with the same requirements (using babel to transpile to js and typescript only for types generation) and this is working for me to generate only the dts files:

return gulp.src(SRC_TS_FILES)
    .pipe(tsProject()).dts
    .pipe(gulp.dest(DEST));

But I was struggling a while until have it working. If I have the "emitDeclarationOnly": true, option in the tsconfig.json nothing is written using this plugin while running tsc from the command line works and generates only the .d.ts files. If I remove the option both behave the same way (i.e.: both .js and .d.ts are generated).

I'm not sure if this is related to the problem described here but I think this behaviour is at least confusing. As this plugin has another way to choose if we want the .js or the .d.ts files it could make sense ignoring the emitDeclarationOnly option to avoid breaking anything if it is included in the tsconfig.

Maybe the original problem was caused by another tsconfig option?

lipedeitos commented 5 years ago

Working o the same situation, if i add option emitDeclarationOnly to my tsconfig.json nothing will be compiled. If i remove emitDeclarationOnly from my tsconfig, both files are compiled .jsx and .d.ts.

I'v tried the @kai670 solution .pipe(tsProject()).dts and it didn't work.

So i did a workaround very similar to @ELLIOTTCABLE, after compiling the .d.ts I delete de jsx manually.

Would be great if emitDeclarationOnly work as it works when um do a tsc --emitDeclarationOnly.

edsrzf commented 4 years ago

I was also experiencing this issue, so I did a bit of debugging and I believe the problem is due to this line of code: https://github.com/ivogabe/gulp-typescript/blob/d0410c2dc37cd4259689e4bc354a8ec68e779823/lib/compiler.ts#L197

When emitDeclarationOnly is on, then jsFileName === undefined, so the entire emitFile is skipped, and nothing is written to either the .js or .dts streams.

From looking at the history this was originally added as a fix for #416 in d4b8c1c, though it looks like the surroundings have changed a fair bit since then.

I'll see if I can figure out a solution and make a pull request. 🤞