1
votes

I've got a Typescript project with a .ts file that is exporting some interfaces and a class. Similar to this:

export interface Tree {
  value: string,
  anotherValue: number,
  children: Tree[]
}

export class Utils {
  static adder(val1: number, val2: number): number {
    return val1 + val2;
  }
  [...blabla some static functions...]
}

Now I build the project (using basic tsc commands - ES2015 modules as target), and in my /dist there'll be a .d.ts file and a .js file.

In the .js file there won't be any interfaces anymore ofcourse. So it looks like:

export class Utils {
  static adder(val1, val2) {
    return val1 + val2;
  }
  [...some more static functions...]
}

And in the .d.ts file I have all my interfaces and the declarations for the class, like:

export interface Tree {
  value: string,
  anotherValue: number,
  children: Tree[]
}

export class Utils {
  static adder(val1: number, val2: number): number;
}

So far so good - everything is looking great.

Now I install my package (/dist folder) into another project and would really like to use my interfaces over there. So I'm doing this:

import {Tree} from "myPackage/dist/myFile"

const myTree: Tree = {someTreeObject}

But Typescript will tell me "Cannot use namespace 'Tree' as a type" - why namespace?

A different try:

import * as Stuff from "myPackage/dist/myFile"

const myTree: Stuff.Tree = {someTreeObject}

But Typescript will tell me "Namespace '"*"' has no exported member 'Tree'."

Then I had a look on some other Typescript declarations and thought "maybe you need to use a namespace" (also the errors sound like that), so I changed myFile to:

export declare namespace myFile {
  interface Tree {
    value: string,
    anotherValue: number,
    children: Tree[]
  }

  class Utils {
    static adder(val1: number, val2: number): number {
      return val1 + val2;
    }
    [...blabla some static functions...]
  }
}

Trying to import {myFile} from "myPackage/dist/myFile" I'll end up with the great "Namespace '"*"' has no exported member 'Tree'." error again.

Can anybody tell me what's going wrong here? I guess it's something really easy but I just don't get it.

Here is a reproduction repo: https://github.com/schadenn/typescript-problem-repro
Either you can npm run build it yourself or just npm install the .tgz package and try to import { NavUtils, TsUtils } from "@test/utils" and use NavUtils.ITree or TsUtils.Omit<ITree, "label">. I also checked in the dist folder so you can see the contents of the package.

Thanks

1
The same happens btw for a different file in that I'm just trying to export a single type. export type Omit<K, P> =... - will output an empty .js file and a .d.ts file with my exported type. No luck trying to import that type though. Gives me all the same errors as whrn I try to import the tree interface.Schadenn
Do you have types property defined in your package.json of myPackage? Do you link myPackage with npm link into your using application?ford04
Yes I have types set correctly in package.json and no I deployed to a Nexus and did a proper npm install. Also I forgot to mention: My "dream" setup would be to have a index.js/index.d.ts that imports and exports all the other modules. But I can't find a best practice on how to export/import types/interfaces/classes - everything I found and tried didn't work.Schadenn
You could let typescript emit those declarations with "declaration": true and consolidate all exports in one index.ts file, look here: stackoverflow.com/questions/57513973/… . Concerning your namespace error, I am not sure, a minimal example would be nice.ford04
I added a reproduction repo to the question.Schadenn

1 Answers

1
votes

Your types cannot be found, as the package currently uses a wrong types path in package.json. You can change the types field like this:

// from
"types": "dist/esm/index.d.ts"

// to
"types": "dist/types/index.d.ts"

So it matches the directory you had set for type declaration emissions in tsconfig.json:

"declarationDir": "dist/types"

If you want to use interface ITree from package @test/utils directly, you can re-export your members. Change your src/index.ts like this:

// from
import * as NavUtils from "./NavigationUtils";
export { NavUtils };

// to
export * from "./NavigationUtils";

In a client, you will then be able to write:

import { ITree } from "@test/utils";

// use your interface here
declare const myTree: ITree;

Concerning Namespaces: I think, you don't need to use them here:

Namespaces are simply named JavaScript objects in the global namespace. [...] Namespaces can be a good way to structure your code in a Web Application, with all dependencies included as script tags in your HTML page.