Skip to content

Commit e96a20a

Browse files
author
Andy Hanson
committed
Don't recommend to install '@types/foo' if that already exists
1 parent c437404 commit e96a20a

6 files changed

+125
-4
lines changed

src/compiler/checker.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2280,16 +2280,22 @@ namespace ts {
22802280
}
22812281

22822282
function errorOnImplicitAnyModule(isError: boolean, errorNode: Node, { packageId, resolvedFileName }: ResolvedModuleFull, moduleReference: string): void {
2283-
const errorInfo = packageId && chainDiagnosticMessages(
2284-
/*details*/ undefined,
2285-
Diagnostics.Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
2286-
getMangledNameForScopedPackage(packageId.name));
2283+
const errorInfo = packageId && !typesPackageExists(packageId.name)
2284+
? chainDiagnosticMessages(
2285+
/*details*/ undefined,
2286+
Diagnostics.Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
2287+
getMangledNameForScopedPackage(packageId.name))
2288+
: undefined;
22872289
errorOrSuggestion(isError, errorNode, chainDiagnosticMessages(
22882290
errorInfo,
22892291
Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type,
22902292
moduleReference,
22912293
resolvedFileName));
22922294
}
2295+
function typesPackageExists(packageName: string): boolean {
2296+
return host.getSourceFiles().some(sf => !!sf.resolvedModules && !!forEachEntry(sf.resolvedModules, r =>
2297+
r && r.packageId && r.packageId.name === getTypesPackageName(packageName)));
2298+
}
22932299

22942300
// An external module with an 'export =' declaration resolves to the target of the 'export =' declaration,
22952301
// and an external module with no 'export =' declaration resolves to the module itself.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/a.ts(2,25): error TS7016: Could not find a declaration file for module 'foo/sub'. '/node_modules/foo/sub.js' implicitly has an 'any' type.
2+
/a.ts(3,25): error TS7016: Could not find a declaration file for module 'bar/sub'. '/node_modules/bar/sub.js' implicitly has an 'any' type.
3+
Try `npm install @types/bar` if it exists or add a new declaration (.d.ts) file containing `declare module 'bar';`
4+
5+
6+
==== /a.ts (2 errors) ====
7+
import * as foo from "foo";
8+
import * as fooSub from "foo/sub";
9+
~~~~~~~~~
10+
!!! error TS7016: Could not find a declaration file for module 'foo/sub'. '/node_modules/foo/sub.js' implicitly has an 'any' type.
11+
import * as barSub from "bar/sub";
12+
~~~~~~~~~
13+
!!! error TS7016: Could not find a declaration file for module 'bar/sub'. '/node_modules/bar/sub.js' implicitly has an 'any' type.
14+
!!! error TS7016: Try `npm install @types/bar` if it exists or add a new declaration (.d.ts) file containing `declare module 'bar';`
15+
16+
==== /node_modules/@types/foo/index.d.ts (0 errors) ====
17+
export const foo: number;
18+
19+
==== /node_modules/@types/foo/package.json (0 errors) ====
20+
{ "name": "@types/foo", "version": "1.2.3" }
21+
22+
==== /node_modules/foo/sub.js (0 errors) ====
23+
const x = 0;
24+
25+
==== /node_modules/foo/package.json (0 errors) ====
26+
{ "name": "foo", "version": "1.2.3" }
27+
28+
==== /node_modules/bar/sub.js (0 errors) ====
29+
const x = 0;
30+
31+
==== /node_modules/bar/package.json (0 errors) ====
32+
{ "name": "bar", "version": "1.2.3" }
33+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [tests/cases/conformance/moduleResolution/untypedModuleImport_noImplicitAny_typesForPackageExist.ts] ////
2+
3+
//// [index.d.ts]
4+
export const foo: number;
5+
6+
//// [package.json]
7+
{ "name": "@types/foo", "version": "1.2.3" }
8+
9+
//// [sub.js]
10+
const x = 0;
11+
12+
//// [package.json]
13+
{ "name": "foo", "version": "1.2.3" }
14+
15+
//// [sub.js]
16+
const x = 0;
17+
18+
//// [package.json]
19+
{ "name": "bar", "version": "1.2.3" }
20+
21+
//// [a.ts]
22+
import * as foo from "foo";
23+
import * as fooSub from "foo/sub";
24+
import * as barSub from "bar/sub";
25+
26+
27+
//// [a.js]
28+
"use strict";
29+
exports.__esModule = true;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== /a.ts ===
2+
import * as foo from "foo";
3+
>foo : Symbol(foo, Decl(a.ts, 0, 6))
4+
5+
import * as fooSub from "foo/sub";
6+
>fooSub : Symbol(fooSub, Decl(a.ts, 1, 6))
7+
8+
import * as barSub from "bar/sub";
9+
>barSub : Symbol(barSub, Decl(a.ts, 2, 6))
10+
11+
=== /node_modules/@types/foo/index.d.ts ===
12+
export const foo: number;
13+
>foo : Symbol(foo, Decl(index.d.ts, 0, 12))
14+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== /a.ts ===
2+
import * as foo from "foo";
3+
>foo : typeof foo
4+
5+
import * as fooSub from "foo/sub";
6+
>fooSub : any
7+
8+
import * as barSub from "bar/sub";
9+
>barSub : any
10+
11+
=== /node_modules/@types/foo/index.d.ts ===
12+
export const foo: number;
13+
>foo : number
14+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// @noImplicitReferences: true
2+
// @strict: true
3+
4+
// @Filename: /node_modules/@types/foo/index.d.ts
5+
export const foo: number;
6+
7+
// @Filename: /node_modules/@types/foo/package.json
8+
{ "name": "@types/foo", "version": "1.2.3" }
9+
10+
// @Filename: /node_modules/foo/sub.js
11+
const x = 0;
12+
13+
// @Filename: /node_modules/foo/package.json
14+
{ "name": "foo", "version": "1.2.3" }
15+
16+
// @Filename: /node_modules/bar/sub.js
17+
const x = 0;
18+
19+
// @Filename: /node_modules/bar/package.json
20+
{ "name": "bar", "version": "1.2.3" }
21+
22+
// @Filename: /a.ts
23+
import * as foo from "foo";
24+
import * as fooSub from "foo/sub";
25+
import * as barSub from "bar/sub";

0 commit comments

Comments
 (0)