Consuming custom typescript typings as NPM package *NOT* under @types namespace

Viewed 600

At my company we are wanting to automate the generation of our typings against out GraphQL API and package those up into a package we can reach for with all of our clients that use the API instead of relying on copy pasta. I've been reading through the TypeScript docs and am a little confuse on how to go about telling TypeScript about these custom typings.

From my readings TypeScript will automatically look for node_modules/@types/*. Unfortunately since this is internal API and we don't want to publish under the DefinitelyTyped repository (I haven't found that you can't explicitly write and @types/package and it be a private module). So at any rate this means whatever we were to name our package will not automatically be looked at by TypeScript.

I read about types and typeRoots thinking these might be the options I need to use. From my reading types is a way that I can specify the @types I want TypeScript to include, a sort of cherry picking option. typeRoots seems like what I should use; however it says only packages under this option will be included. My assumption here is I would need to do something like the following (we would still want the definitions under @types):

{
  "compilerOptions": {
    "typeRoots": ["node_modules/@types", "node_modules/@companyOrg/customTypings"]
  }
}

Is anyone out there doing a similar thing and found a way for TypeScript to include your custom typings that are not under the @types umbrella? Please note I'm not talking about creating a custom.d.ts in the project directory, but consuming an NPM packages similar to @types/react except something like @company/our-types.

Current tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "preserveSymlinks": true,
    "typeRoots": [
      "node_modules/@types",
      "node_modules/@companyOrg/customTypings",
    ],
  },
  "include": [
    "src"
  ],
}

Also I am working locally on this so I have used yarn link @company/our-types perhaps this is where the problem is originating from. I have checked the path several times and everything seems fine though.

1 Answers

Let me show the example that works for me. There are 2 packages: types (it can be any name) and consumer. Types package contains my typings in form of d.ts files, and I have index.d.ts in the root (this file is used as an entry point by convention but it can be redefined using types field in package.json)

// types/index.d.ts
declare namespace MyLib {
    interface MyInterface {
        id: string;
    }
}

export = MyLib;

I do npm link types into consumer and add "types": "*" to dependencies of consumer.

{
  "name": "consumer",
  "version": "1.0.0",
  "dependencies": {
    "typescript": "^3.8.3",
    "types": "*" // <----
  }
}

Right after that I can use types exported from types in consumer:

// consumer/index.ts
import { MyInterface } from "types";

const y: MyInterface = { id: "1" };

It works because TS is looking for types definitions in all dependencies and allows you to use them without any additional configuration.

Related