Search code examples
typescriptclassinner-classesextendoverwrite

Overwrite / extend typescript class expressions


My company has developed a own test framework for the software, because it's not possible to use an open-source framework in the context of the software we develop.

Anyway, I wrote Typescript Definition Files to improve the code completion for VS Code, but I can't make it work for the following setup:

The following class is used to define unit tests. It provides some functions, e.g. for assertions. The main problem is the util-namespace. You can pass a function which is actually the unit test. Note that the this-object of that function points to the unit test class so that the passed function can make use of the functions of the unit test (internally the passed function will be called with "unitTest.call(this)" to set the this object of the function to the unit test instance)

class UnitTest {
    constructor(unitTest: (this: UnitTest) => void);
    .
    .
    .
    util = Util; // Referes to the Util-Class (it's a class because its the only possibility in typescript for nesting 

The Util-class provides some general functions which are useful for writing tests

class Util {
    static createFile(filePath: string): File;
    .
    .
    .
}

If you declare a Unit Test like this, everything works fine:

var unitTest = new UnitTest(function() {
     this.util.createFile("..."); // VS-Code provides code completion for that functions of the unit-test-namespace
});

The problem is, that the util-class (which is used for code encapsulation) can be extended in every project. You can define a script following a specific name schema and the testframework dynamically loads that script and provides that functions in the util namespace, e.g. "test.util.myProject.js"

module.exports = {
    myCustomUtilFunction = function () { ... }
};

Just by providing the script you can use that function in your unit test:

var unitTest = new UnitTest(function() {
 this.util.myCustomUtilFunction();
});

But I can't cover this with the typescript definition file. VS-Code will not provide any code completion for the custom util functions because it's missing in the typescript definition of the test framework. I tried to extend the Util-class as follow, but VS-Code doesn't care:

class Util {
    static myCustomUtilFunction(): void;
}

Any idea how to solve this?


To make it easier to understand, here is the complete setup
testframework.d.ts

class UnitTest {
    constructor(unitTest: (this: UnitTest) => 

    util = Util;
}

class Util {
    static createFile(filePath: string): File;
}

myExtendedUtilNamespace.d.ts

class Util {
    static myCustomUtilFunction(): void;
}

unitTests.js

var unitTest = new UnitTest(function() {
    this.util.createFile("..."); // works
    this.util.myCustomUtilFunction(); // does not work
});

Solution

  • To me is sounds like the Util class is never instantiated. If that is correct it shouldn't be a class. A namespace is more fitting in this context. Namespaces are also able to be merged between declaration files.

    // testframework.d.ts
    class UnitTest {
        constructor(unitTest: (this: UnitTest) => void);
    
        util = Util;
    }
    
    declare namespace Util {
        export function createFile(filePath: string): File;
    }
    
    // myExtendedUtilNamespace.d.ts
    declare namespace Util {
      export function myCustomUtilFunction(): void;
    }
    

    See the TypeScript Handbook about namespaces: https://www.typescriptlang.org/docs/handbook/namespaces.html