Skip to content

Cannot find type definition file for ambient declaration module #34749

Open

Description

TypeScript Version: 3.6 to 3.8.0-dev.20191025

Search Terms: ambient module triple slash reference path declaration

Code

// A *self-contained* demonstration of the problem follows...
[typings/somemodule/index.d.ts]
declare module "somemodule"
{
  export namespace common {
    export interface Foo {
      bar: string;
      fuzz: Number;
    }
  }
}

[src/index.ts]
/// <reference path="../typings/somemodule/index.d.ts" />

Typescript 3.5.3 works as expected, anything at or above 3.6 has the same issue..

When running tsc -d, for a manually created declaration file, the triple slash reference path file should be preserved in the output declaration file. This particular declaration file acts as a shim for an existing library whose type definitions are incomplete and is to be included as-is and without transpiler manipulation in the output declaration file. This provides accurate intellisense for package consumers and ensures build errors do not occur.

Expected behavior:
Maintain the same triple-slash reference path in the .d.ts file as was in the .ts file.

[dist/index.d.ts]
/// <reference path="../typings/somemodule/index.d.ts" />

Actual behavior:
The reference path is changed to reference types and the relative path is also broken:

[dist/index.d.ts]
/// <reference types="typings/somemodule" />

This causes consuming applications of the package to receive the following build error:
Cannot find type definition file for 'typings/somemodule'.

I have been unsuccessful in manipulating the consuming application to build correctly or provide correct intellisense with the updated directive. The original directive must be preserved.

Playground Link:

Related Issues: I believe this is where the issue was introduced: #32878

Activity

  1. jdom commented on Oct 29, 2019

    @jdom
    Member

    I'm repro'ing this too. I was updating from 3.3 to 3.6 and hit this issue. Now I'm falling back to 3.5 which doesn't repro this issue

  2. weswigham commented on Oct 30, 2019

    @weswigham
    Member

    IIRC reference types is only used when a package is within a node_modules folder - is your source tree within a node_modules folder or using some other method to make that path seem valid to TS? What are your compilerOptions? Are you using baseUrl?

  3. jdom commented on Oct 30, 2019

    @jdom
    Member

    Our source tree is not with a node_modules folder, and indeed we are using baseUrl. But in the particular project I'm seeing this failing (it could be many more, but compilation just stops there after this failure), the value for baseUrl is ../ and also mergeReferenceces is true, as this small project is built within some other bigger project:

    {
      "extends": "../../../tsconfig.base.json",
      "compilerOptions": {
        "baseUrl": "../",
        "composite": true,
        "jsx": "react",
        "outDir": "../../Output/Content/Scripts",
        "paths": {
          "*": [
            "*"
          ]
        },
        "rootDir": "../"
      },
      "include": [
        "**/*"
      ],
      "mergeReferences": true
    }
    

    And the base config referenced in the previous config is this:

    {
      "compileOnSave": true,
      "compilerOptions": {
        "declaration": true,
        "declarationMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "forceConsistentCasingInFileNames": true,
        "inlineSources": true,
        "jsx": "react",
        "lib": [
          "dom",
          "es2015",
          "es2015.collection",
          "es2015.promise",
          "es2015.iterable",
          "es5",
          "scripthost"
        ],
        "module": "amd",
        "moduleResolution": "node",
        "noEmitHelpers": true,
        "noImplicitAny": true,
        "noImplicitThis": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "removeComments": false,
        "sourceMap": true,
        "strictBindCallApply": true,
        "stripInternal": true,
        "target": "es5",
        "types": []
      },
    }
    
  4. jdom commented on Oct 30, 2019

    @jdom
    Member

    Scrap a little bit of that. The failure is happening in the project I mentioned above, but the incorrect definition file is being created in a project it depends on. The project where the incorrect dependency is being generated has this configuration:

    {
      "extends": "../tsconfig.base.json",
      "compilerOptions": {
        "baseUrl": "TypeScript",
        "composite": true,
        "outDir": "Output/Content/Scripts",
        "paths": {
          "*": [
            "*"
          ]
        },
        "rootDir": "TypeScript",
      },
      "include": [
        "TypeScript/**/*",
        "../Framework.Client/TypeScript/Definitions/FxReactCommon.d.ts",
        "../Framework.Client/TypeScript/Definitions/redux.d.ts"
      ]
    }
    

    The base config file is the same as what i pasted in my previous comment.

  5. weswigham commented on Oct 30, 2019

    @weswigham
    Member

    It's the baseUrl flag. The emitter is configured to prefer non-relative reference types style refs where possible, and the baseUrl parameter alters resolution to allow non-relative references starting at the location specified by the baseUrl.

  6. weswigham commented on Oct 30, 2019

    @weswigham
    Member

    In short: The baseUrl flag (combined with commonjs module resolution rules regarding extensions and indexes) is telling the compiler that it's OK to reference that file via the path typings/somemodule, and it's now using that knowledge to generate a "nicer" (and usually more portable) reference.

  7. weswigham commented on Oct 30, 2019

    @weswigham
    Member

    Julian Dominguez (@jdom) would you be able to move your typings folder out of your baseUrl directory? Since you're not shipping them into the combined root that a baseUrl resolution relies on, it doesn;t really make sense for them to be under the input baseUrl directory.

  8. tschettler commented on Oct 31, 2019

    @tschettler
    Author

    Yes, I use baseUrl and if I don't, the triple slash reference is left alone. Here's my tsconfig.json.

    {
      "compileOnSave": false,
      "compilerOptions": {
        "baseUrl": ".",
        "declaration": true,
        "declarationDir": "dist/types",
        "emitDecoratorMetadata": true,
        "esModuleInterop": true,
        "experimentalDecorators": true,
        "lib": [
          "es2015",
          "es2016",
          "es2017",
          "dom"
        ],
        "module": "es2015",
        "moduleResolution": "node",
        "noImplicitAny": false,
        "outDir": "dist/lib",
        "removeComments": true,
        "sourceMap": true,
        "target": "es6",
        "typeRoots": [
          "node_modules/@types",
          "typings"
        ]
      },
      "include": [
        "src/**/*.ts"
      ],
      "exclude": [
        "dist",
        "node_modules",
        "**/*.json",
        "**/*.spec.ts"
      ]
    }
    

    Does this mean baseUrl cannot be used when the project uses triple slash reference paths?

  9. jdom commented on Oct 31, 2019

    @jdom
    Member

    I'm a little hesitant to do this change, as we have tons of legacy external tooling that works with the current structure, and we also generate different definitions and bundles for different SDKs. If there is a way to get the previous behavior (ie: since my source code is explicitly using a relative reference, keep it relative in the emitter), then I'd certainly prefer that. Do you think it can be achieved with the current release?

  10. dfreeman commented on Nov 5, 2019

    @dfreeman
    Contributor

    We just ran into something similar to this; I'm unclear on whether it's exactly the same issue or just related on the surface. We have a handful of internal packages that declare types for public ones that don't have their own declarations (essentially like a miniature internal DT).

    Consumers of these typings include an import somewhere in their source and then are able to otherwise interact with the target packages normally:

    import '@our-org/types~some-package';
    import { Something } from 'some-package';
    
    export const foo = {
      something: new Something()
    };

    Up to TS 3.5, when emitting declarations in this scenario, we'd get output like this:

    export declare const foo: {
      something: import('some-package').Something
    }

    As of 3.6, we instead see:

    /// <reference types="node_modules/@our-org/types~some-package" />
    
    export declare const foo: {
      something: import('some-package').Something
    }

    While it definitely seems like a good thing to have that reference included instead of relying on the downstream consumer to have imported the declarations themselves, the path emitted doesn't seem to resolve correctly. I think the leading node_modules/ is causing issues?

    We do have a baseUrl set (and can't easily migrate off it because of a fair amount of paths usage), but I'm a bit surprised that node_modules is appearing in the path at all.

    Edit: I just realized this behavior is different based on the declarationDir we use. If it's outside the project directory (and thus outside the baseUrl), the path includes node_modules, but if it's within the project directory, it doesn't. Is it expected that the place declarations are being emitted to would impact their contents?

  11. Griffork commented on Dec 7, 2020

    @Griffork

    I'm running into this problem too, in a umd common project that's included on the server (which is a commonjs node project) and the client (which is an amd web-browser project). This causes compilation of both the server and the client to fail.
    Additionally the ./ and .d.ts are removed from the path, so /// <reference path="./GlobalDefinitions.d.ts" /> becomes /// <reference types="globaldefinitions" /> which fails.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs InvestigationThis issue needs a team member to investigate its status.

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions