Skip to content

Cannot find type definition file for ambient declaration module #34749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
tschettler opened this issue Oct 26, 2019 · 11 comments
Open

Cannot find type definition file for ambient declaration module #34749

tschettler opened this issue Oct 26, 2019 · 11 comments
Labels
Needs Investigation This issue needs a team member to investigate its status.
Milestone

Comments

@tschettler
Copy link

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

@jdom
Copy link
Member

jdom commented Oct 29, 2019

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

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Oct 30, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.8.0 milestone Oct 30, 2019
@weswigham
Copy link
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?

@jdom
Copy link
Member

jdom commented Oct 30, 2019

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": []
  },
}

@jdom
Copy link
Member

jdom commented Oct 30, 2019

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.

@weswigham
Copy link
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.

@weswigham
Copy link
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.

@weswigham
Copy link
Member

@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.

@tschettler
Copy link
Author

tschettler commented Oct 31, 2019

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?

@jdom
Copy link
Member

jdom commented Oct 31, 2019

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?

@dfreeman
Copy link
Contributor

dfreeman commented Nov 5, 2019

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?

@Griffork
Copy link

Griffork commented Dec 7, 2020

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
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

No branches or pull requests

6 participants