Pregunta

When it compiles my code, TypeScript includes an __extends declaration at the top of every file:

var __extends = this.__extends || function (d, b) {
    /* istanbul ignore next */
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

This works fine behind-the-scenes, but it creates an inconsistency when it comes to using something like karma-coverage to generate reports. This declaration contains two function calls and a branch in the code (the || usage), which only ever get exercised on the first declaration, leaving dozens (if not hundreds) of subsequent declarations for which there is no coverage. This makes a file with otherwise 100% code coverage look sorely uncovered in the coverage reports.

Has anyone solved this problem?

¿Fue útil?

Solución 3

Since 2.1, typescript support for external helper library, all the emitted function goes to the tslib package

npm install --save tslib

change your tsconfig:

{
    "compilerOptions": {
        //all the other stuff
        "importHelpers": true
    }
}

then TypeScript will automatically import tslib package if necessary like example below

var tslib_1 = require("tslib");

var MyClass = (function (_super) {
    tslib_1.__extends(MyClass, _super);
    function MyClass() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return MyClass;
}(controller_1.Controller));

Otros consejos

I found a work item at the typescript codeplex. I hope the typescript guys solve this issue soon. You can find more on that here: typescript workitem 2002

I just created a function in my scripts task that appends a header to the top of any file that uses inheritance. This boosted by code coverage a lot. I'm using istanbul, so my function looks like this:

function istanbulIgnoreTypeScriptExtend() {
    var tsExtends = /^var __extends =/;
    return through.obj(function(file, enc, done) {
        if (file.isBuffer() && tsExtends.test(file.contents)) {
            file.contents = Buffer.concat([
                new Buffer('/* istanbul ignore next: TypeScript extend */' + os.EOL),
                file.contents
            ]);
        }
        this.push(file);
        done();
    });
}

I could actually publish it as a gulp plugin, but I'm hoping there are new ways to fix the problem soon.

Here is an example of using the function @jedmao provided in their answer with a gulp task. I've modified it slightly to handle the var __extends= not being the first thing in the file (e.g. if you have a 'use strict' or a /// <references tag). You should probably also use os.EOL as jedmao did rather than a \n as I am doing here.

var gulp     = require('gulp');
var through2 = require('through2');

gulp.task('my-gulp-task', function() {
    gulp.src('*.ts')
        .pipe(myTypeScriptCompiler())
        .pipe(istanbulIgnoreTypeScriptExtend())
        .pipe(gulp.dest('myDestFolder'));
});

function istanbulIgnoreTypeScriptExtend() {
    var tsExtends = /var __extends =/;
    return through2.obj(function(file, enc, done) {
        if (file.isBuffer() && tsExtends.test(file.contents)) {
            var rows = file.contents.toString().split('\n');
            for (var i = 0; i < rows.length; i++) {
                if (rows[i].indexOf('var __extends =') === 0) {
                    rows.splice(i, 0, '/* istanbul ignore next: TypeScript extend */');
                    break;
                }
            }
            file.contents = new Buffer(rows.join('\n'));
        }
        this.push(file);
        done();
    });
}

The typescript compiler will generate this on top of every file that has the extends keyword. The only way to make this a single use is compile to a single js file with --out compiler flag.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top