Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript blocks node/module factory pattern: error TS4060

When using ES6 module syntax to export a factory function which returns an instance of a class Typescript produce the following error:

error TS4060: Return type of exported function has or is using private name 'Paths'.

From paths.ts:

//Class scoped behind the export
class Paths {

    rootDir: string;

    constructor(rootDir: string) {

        this.rootDir = rootDir;

    };


};

//Factory function: returns instances of Paths
export default function getPaths(rootDir:string){ 

    return new Paths(rootDir);

};

This legitimate ES6 javascript. However, the only work around i've found is to export the class. Which means when it is compiled to ES6 the Class is being exported defeating the purpose of scoping it in the module. e.g:

//Class now exported
export class Paths {

    rootDir: string;

    constructor(rootDir: string) {

        this.rootDir = rootDir;

    };


};

//Factory function: returns instances of Paths
export default function getPaths(rootDir:string){ 

    return new Paths(rootDir);

};

Am I missing something? It seems to me that this pattern should be supported by typescript, especially in ES6 compilation where the pattern becomes more prominent.

like image 821
Michael Price Avatar asked Sep 15 '25 11:09

Michael Price


1 Answers

This is only an error if you're trying to automatically produce a declaration file, because there's nothing that TypeScript could emit into that file that would reproduce the shape of your module with 100% precision.

If you want to have the compiler produce the declaration file, you'll need to provide a type that you can use for the return type of getPaths. You could use an inline type:

export default function getPaths(rootDir:string): { rootDir: string; } { 
  return new Paths(rootDir);
};

Or define an interface:

class Paths implements PathShape {
    rootDir: string;
    constructor(rootDir: string) {
        this.rootDir = rootDir;
    }
}
export interface PathShape {
    rootDir:string;
}
export default function getPaths(rootDir:string): PathShape { 
  return new Paths(rootDir);
}

The second is probably preferred because this gives people who import your module some name to use to refer to the type of the return value of getPaths.

like image 105
Ryan Cavanaugh Avatar answered Sep 17 '25 00:09

Ryan Cavanaugh