Fix incorrect suggestion for package that bundles types (#45507)

* Fix incorrect suggestion for package that bundles types

* determine if a package ships types from its files

* update new error message
This commit is contained in:
Gabriela Araujo Britto 2021-08-20 11:12:34 -07:00 committed by GitHub
parent e00722f262
commit 84b057828e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 132 additions and 10 deletions

View file

@ -294,16 +294,20 @@ namespace ts {
}
export function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker {
const getPackagesSet = memoize(() => {
const set = new Set<string>();
const getPackagesMap = memoize(() => {
// A package name maps to true when we detect it has .d.ts files.
// This is useful as an approximation of whether a package bundles its own types.
// Note: we only look at files already found by module resolution,
// so there may be files we did not consider.
const map = new Map<string, boolean>();
host.getSourceFiles().forEach(sf => {
if (!sf.resolvedModules) return;
forEachEntry(sf.resolvedModules, r => {
if (r && r.packageId) set.add(r.packageId.name);
if (r && r.packageId) map.set(r.packageId.name, r.extension === Extension.Dts || !!map.get(r.packageId.name));
});
});
return set;
return map;
});
// Cancellation that controls whether or not we can cancel in the middle of type checking.
@ -3417,11 +3421,17 @@ namespace ts {
/*details*/ undefined,
Diagnostics.If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1,
packageId.name, mangleScopedPackageName(packageId.name))
: chainDiagnosticMessages(
/*details*/ undefined,
Diagnostics.Try_npm_i_save_dev_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
moduleReference,
mangleScopedPackageName(packageId.name))
: packageBundlesTypes(packageId.name)
? chainDiagnosticMessages(
/*details*/ undefined,
Diagnostics.If_the_0_package_actually_exposes_this_module_try_adding_a_new_declaration_d_ts_file_containing_declare_module_1,
packageId.name,
moduleReference)
: chainDiagnosticMessages(
/*details*/ undefined,
Diagnostics.Try_npm_i_save_dev_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
moduleReference,
mangleScopedPackageName(packageId.name))
: undefined;
errorOrSuggestion(isError, errorNode, chainDiagnosticMessages(
errorInfo,
@ -3430,7 +3440,10 @@ namespace ts {
resolvedFileName));
}
function typesPackageExists(packageName: string): boolean {
return getPackagesSet().has(getTypesPackageName(packageName));
return getPackagesMap().has(getTypesPackageName(packageName));
}
function packageBundlesTypes(packageName: string): boolean {
return !!getPackagesMap().get(packageName);
}
function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol;

View file

@ -6027,6 +6027,11 @@
"category": "Error",
"code": 7057
},
"If the '{0}' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module '{1}';`": {
"category": "Error",
"code": 7058
},
"You cannot rename this element.": {
"category": "Error",

View file

@ -0,0 +1,27 @@
tests/cases/conformance/moduleResolution/index.ts(2,24): error TS7016: Could not find a declaration file for module 'foo/other'. 'tests/cases/conformance/moduleResolution/node_modules/foo/other.js' implicitly has an 'any' type.
If the 'foo' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module 'foo/other';`
==== tests/cases/conformance/moduleResolution/index.ts (1 errors) ====
import * as Foo from "foo";
import * as Other from "foo/other"/*1*/;
~~~~~~~~~~~
!!! error TS7016: Could not find a declaration file for module 'foo/other'. 'tests/cases/conformance/moduleResolution/node_modules/foo/other.js' implicitly has an 'any' type.
!!! error TS7016: If the 'foo' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module 'foo/other';`
==== tests/cases/conformance/moduleResolution/node_modules/foo/package.json (0 errors) ====
{
"name": "foo",
"version": "1.0.0"
}
==== tests/cases/conformance/moduleResolution/node_modules/foo/index.js (0 errors) ====
var foo = 0;
module.exports = foo;
==== tests/cases/conformance/moduleResolution/node_modules/foo/index.d.ts (0 errors) ====
declare const foo: any;
export = foo;
==== tests/cases/conformance/moduleResolution/node_modules/foo/other.js (0 errors) ====
module.exports = {};

View file

@ -0,0 +1,26 @@
//// [tests/cases/conformance/moduleResolution/declarationNotFoundPackageBundlesTypes.ts] ////
//// [package.json]
{
"name": "foo",
"version": "1.0.0"
}
//// [index.js]
var foo = 0;
module.exports = foo;
//// [index.d.ts]
declare const foo: any;
export = foo;
//// [other.js]
module.exports = {};
//// [index.ts]
import * as Foo from "foo";
import * as Other from "foo/other"/*1*/;
//// [index.js]
"use strict";
exports.__esModule = true;

View file

@ -0,0 +1,14 @@
=== tests/cases/conformance/moduleResolution/index.ts ===
import * as Foo from "foo";
>Foo : Symbol(Foo, Decl(index.ts, 0, 6))
import * as Other from "foo/other"/*1*/;
>Other : Symbol(Other, Decl(index.ts, 1, 6))
=== tests/cases/conformance/moduleResolution/node_modules/foo/index.d.ts ===
declare const foo: any;
>foo : Symbol(foo, Decl(index.d.ts, 0, 13))
export = foo;
>foo : Symbol(foo, Decl(index.d.ts, 0, 13))

View file

@ -0,0 +1,14 @@
=== tests/cases/conformance/moduleResolution/index.ts ===
import * as Foo from "foo";
>Foo : any
import * as Other from "foo/other"/*1*/;
>Other : any
=== tests/cases/conformance/moduleResolution/node_modules/foo/index.d.ts ===
declare const foo: any;
>foo : any
export = foo;
>foo : any

View file

@ -0,0 +1,23 @@
// @noImplicitAny: true
// @noImplicitReferences: true
// @filename: node_modules/foo/package.json
{
"name": "foo",
"version": "1.0.0"
}
// @filename: node_modules/foo/index.js
var foo = 0;
module.exports = foo;
// @filename: node_modules/foo/index.d.ts
declare const foo: any;
export = foo;
// @filename: node_modules/foo/other.js
module.exports = {};
// @filename: index.ts
import * as Foo from "foo";
import * as Other from "foo/other"/*1*/;