This commit is contained in:
Andy Hanson 2016-10-28 10:47:09 -07:00
parent b866bf1763
commit e1bd44d95c
11 changed files with 191 additions and 100 deletions

View file

@ -112,7 +112,8 @@ namespace ts {
} }
} }
export function getEffectiveTypeRoots(options: CompilerOptions, host: { directoryExists?: (directoryName: string) => boolean, getCurrentDirectory?: () => string }): string[] | undefined { //neater
export function getEffectiveTypeRoots(options: CompilerOptions, host: { directoryExists?: (directoryName: string) => boolean, getCurrentDirectory?: () => string }, notDefault = false): string[] | undefined {
if (options.typeRoots) { if (options.typeRoots) {
return options.typeRoots; return options.typeRoots;
} }
@ -125,19 +126,9 @@ namespace ts {
currentDirectory = host.getCurrentDirectory(); currentDirectory = host.getCurrentDirectory();
} }
return currentDirectory !== undefined && getDefaultTypeRoots(currentDirectory, host); if (currentDirectory !== undefined && !notDefault) {
} return getDefaultTypeRoots(currentDirectory, host);
}
//Does this duplicate functionality in resolveTypeReferenceDirective?
/**
* Load a module from typeRoots.
* This should be done in *addition* to climbing ancestor directories and looking for node_modules/@types.
* It should be done after looking for TypeScript but before JavaScript.
* This should only be done for global imports.
*/
function loadModuleFromTypeRoots(moduleName: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
return forEach(getEffectiveTypeRoots(state.compilerOptions, state.host), root =>
loadNodeModuleFromDirectoryHelper(Extensions.DtsOnly, combinePaths(root, moduleName), failedLookupLocations, state));
} }
/** /**
@ -152,18 +143,12 @@ namespace ts {
let typeRoots: string[]; let typeRoots: string[];
while (true) { forEachAncestorDirectory(currentDirectory, directory => {
const atTypes = combinePaths(currentDirectory, nodeModulesAtTypes); const atTypes = combinePaths(directory, nodeModulesAtTypes);
if (host.directoryExists(atTypes)) { if (host.directoryExists(atTypes)) {
(typeRoots || (typeRoots = [])).push(atTypes); (typeRoots || (typeRoots = [])).push(atTypes);
} }
});
const parent = getDirectoryPath(currentDirectory);
if (parent === currentDirectory) {
break;
}
currentDirectory = parent;
}
return typeRoots; return typeRoots;
} }
@ -174,7 +159,6 @@ namespace ts {
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups
* is assumed to be the same as root directory of the project. * is assumed to be the same as root directory of the project.
*/ */
//does this duplicate code from loadModuleFromTypeRoots???
export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations { export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
const traceEnabled = isTraceEnabled(options, host); const traceEnabled = isTraceEnabled(options, host);
const moduleResolutionState: ModuleResolutionState = { const moduleResolutionState: ModuleResolutionState = {
@ -206,23 +190,19 @@ namespace ts {
const failedLookupLocations: string[] = []; const failedLookupLocations: string[] = [];
// Check primary library paths // Check primary library paths
//This seems like redundant code!
if (typeRoots && typeRoots.length) { if (typeRoots && typeRoots.length) {
if (traceEnabled) { if (traceEnabled) {
trace(host, Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); trace(host, Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", "));
} }
for (const typeRoot of typeRoots) { const resolved = resolvedTypeScriptOnly(fooTypeRoots(typeRoots, typeReferenceDirectiveName, failedLookupLocations, moduleResolutionState));
const candidate = combinePaths(typeRoot, typeReferenceDirectiveName); if (resolved) {
const resolved = resolvedTypeScriptOnly(loadNodeModuleFromDirectoryHelper(Extensions.DtsOnly, candidate, failedLookupLocations, moduleResolutionState)); if (traceEnabled) {
if (resolved) { trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolved, true);
if (traceEnabled) {
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolved, true);
}
return {
resolvedTypeReferenceDirective: { primary: true, resolvedFileName: resolved },
failedLookupLocations
};
} }
return {
resolvedTypeReferenceDirective: { primary: true, resolvedFileName: resolved },
failedLookupLocations
};
} }
} }
else { else {
@ -239,11 +219,7 @@ namespace ts {
if (traceEnabled) { if (traceEnabled) {
trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup);
} }
//should this just be loadModuleFromTypeRoots ????
//!!!!!!
//resolvedFile = resolvedTypeScriptOnly(loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*checkOneLevel*/ false));
resolvedFile = resolvedTypeScriptOnly(loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState)); resolvedFile = resolvedTypeScriptOnly(loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState));
//TODO: this used to look from @types too, but isn't that silly?
if (traceEnabled) { if (traceEnabled) {
if (resolvedFile) { if (resolvedFile) {
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile, false); trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile, false);
@ -264,6 +240,24 @@ namespace ts {
}; };
} }
/**
* Load a module from typeRoots. Used by node/classic resolvers.
* This should be done in *addition* to climbing ancestor directories and looking for node_modules/@types.
* It should be done after looking for TypeScript but before JavaScript.
* This should only be done for global imports.
*/
function loadModuleFromTypeRoots(moduleName: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
//don't want to include the default node_modules/@types type roots since that's already been looked for in the node_modules/@types search.
const roots = getEffectiveTypeRoots(state.compilerOptions, state.host, /*notDefault*/ true);
return fooTypeRoots(roots, moduleName, failedLookupLocations, state);
}
//name: searchInTypeRoots
function fooTypeRoots(typeRoots: string[] | undefined, moduleName: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
return forEach(typeRoots, root =>
loadNodeModuleFromDirectoryHelper(Extensions.DtsOnly, combinePaths(root, moduleName), failedLookupLocations, state));
}
/** /**
* Given a set of options, returns the set of type directive names * Given a set of options, returns the set of type directive names
* that should be included for this program automatically. * that should be included for this program automatically.
@ -558,7 +552,6 @@ namespace ts {
const result = tryResolve(Extensions.TypeScript) || tryTypeRoots() || tryResolve(Extensions.JavaScript); //Should we try typeroots first? last? const result = tryResolve(Extensions.TypeScript) || tryTypeRoots() || tryResolve(Extensions.JavaScript); //Should we try typeroots first? last?
if (result) { if (result) {
//note: isExternalLibraryImport appears to be identical to nonRelative!
const { resolved, isExternalLibraryImport } = result; const { resolved, isExternalLibraryImport } = result;
return createResolvedModuleWithFailedLookupLocations(resolved && resolvedWithRealpath(resolved, host, traceEnabled), isExternalLibraryImport, failedLookupLocations); return createResolvedModuleWithFailedLookupLocations(resolved && resolvedWithRealpath(resolved, host, traceEnabled), isExternalLibraryImport, failedLookupLocations);
} }
@ -584,11 +577,11 @@ namespace ts {
} }
} }
//rename //TODO: this may duplicate effort from tryResolve!
function tryTypeRoots(): { resolved: Resolved, isExternalLibraryImport: boolean } | undefined { function tryTypeRoots(): { resolved: Resolved, isExternalLibraryImport: boolean } | undefined {
if (nonRelative) { if (nonRelative) {
const resolved = loadModuleFromTypeRoots(moduleName, failedLookupLocations, state); //loadModuleFromAnyTypeLocation(moduleName, containingDirectory, failedLookupLocations, state); const resolved = loadModuleFromTypeRoots(moduleName, failedLookupLocations, state); //loadModuleFromAnyTypeLocation(moduleName, containingDirectory, failedLookupLocations, state);
return resolved && { resolved, isExternalLibraryImport: true } return resolved && { resolved, isExternalLibraryImport: true };
} }
} }
} }
@ -685,7 +678,6 @@ namespace ts {
} }
} }
//share code?
function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined { function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
const nodeModulesFolder = combinePaths(directory, "node_modules"); const nodeModulesFolder = combinePaths(directory, "node_modules");
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host);
@ -695,8 +687,6 @@ namespace ts {
loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state); loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state);
} }
//If we're calling this for @types, we could simplify. Don't need to look for "main"
//In those cases extensions === Extensions.DtsOnly
function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined { function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
const packageJsonPath = pathToPackageJson(candidate); const packageJsonPath = pathToPackageJson(candidate);
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); //We do the check a second time??? silly! const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); //We do the check a second time??? silly!
@ -745,53 +735,28 @@ namespace ts {
return combinePaths(directory, "package.json"); return combinePaths(directory, "package.json");
} }
//name //check uses
//doc
/*function fromFileOrDirectory(extensions: Extensions, directory: string, moduleName: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
const directoryExists = directoryProbablyExists(directory, state.host);
const candidate = normalizePath(combinePaths(directory, moduleName));
return loadModuleFromFile(extensions, candidate, failedLookupLocations, !directoryExists, state) ||
//This shouldn't be node-specific!
//... but it is ...
loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, !directoryExists, state);
}*/
function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined { function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
return loadModuleFromNodeModules(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, /*checkOneLevel*/ false, /*typesOnly*/ true); //should this be Extensions.DtsOnly??? That would match loadModulesFromTypeRoots
return loadModuleFromNodeModules(Extensions.TypeScript, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ true);
} }
//Dont' do @types lookup here, use loadModuleFromTypeRoots instead! //Dont' do @types lookup here, use loadModuleFromTypeRoots instead!
//"checkOneLevel" is never used!!! //"checkOneLevel" is never used!!!
function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, checkOneLevel = false, typesOnly = false): Resolved | undefined { function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, typesOnly = false): Resolved | undefined {
directory = normalizeSlashes(directory); directory = normalizeSlashes(directory);
//forEachAncestorDirectory helper //forEachAncestorDirectory helper
while (true) { return forEachAncestorDirectory(directory, directory => {
if (getBaseFileName(directory) !== "node_modules") { if (getBaseFileName(directory) !== "node_modules") {
const resolved = tryInDirectory(extensions, moduleName, directory, failedLookupLocations, state, typesOnly); return loadModuleFromSingleNodeModules(extensions, moduleName, directory, failedLookupLocations, state, typesOnly);
if (resolved) {
return resolved;
}
} }
});
const parentPath = getDirectoryPath(directory);
if (parentPath === directory || checkOneLevel) {
return undefined;
}
directory = parentPath;
}
} }
//name /** Load a package from a single node_modules directory. Tries both regular and @types lookup. */
function tryInDirectory(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, typesOnly = false): Resolved | undefined { function loadModuleFromSingleNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, typesOnly = false): Resolved | undefined {
//const nodeModulesFolder = combinePaths(directory, "node_modules");
//return fromFileOrDirectory(extensions, nodeModulesFolder, moduleName, failedLookupLocations, state);
const packageResult = typesOnly ? undefined : loadModuleFromNodeModulesFolder(extensions, moduleName, directory, failedLookupLocations, state); const packageResult = typesOnly ? undefined : loadModuleFromNodeModulesFolder(extensions, moduleName, directory, failedLookupLocations, state);
//@types lookup should probably be dts only
return packageResult || loadModuleFromNodeModulesFolder(extensions, combinePaths("@types", moduleName), directory, failedLookupLocations, state); return packageResult || loadModuleFromNodeModulesFolder(extensions, combinePaths("@types", moduleName), directory, failedLookupLocations, state);
//TODO: don't do this is we have typeRoots set?
//|| loadModuleFromNodeModulesFolder(extensions, combinePaths("@types", moduleName), directory, failedLookupLocations, state);
} }
export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
@ -817,7 +782,6 @@ namespace ts {
} }
if (extensions === Extensions.TypeScript) { if (extensions === Extensions.TypeScript) {
// If we didn't find the file normally, look it up in @types and in type roots. // If we didn't find the file normally, look it up in @types and in type roots.
//Test "prefer typings to js during second resolution pass"
return loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state) || loadModuleFromTypeRoots(moduleName, failedLookupLocations, state); return loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state) || loadModuleFromTypeRoots(moduleName, failedLookupLocations, state);
} }
} }
@ -830,18 +794,10 @@ namespace ts {
/** Climb up parent directories looking for a module. */ /** Climb up parent directories looking for a module. */
function loadModuleFromAncestorDirectories(extensions: Extensions, moduleName: string, containingDirectory: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined { function loadModuleFromAncestorDirectories(extensions: Extensions, moduleName: string, containingDirectory: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
while (true) { return forEachAncestorDirectory(containingDirectory, directory => {
const searchName = normalizePath(combinePaths(containingDirectory, moduleName)); const searchName = normalizePath(combinePaths(directory, moduleName));
const referencedSourceFile = loadModuleFromFile(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state); return loadModuleFromFile(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state);
if (referencedSourceFile) { });
return referencedSourceFile;
}
const parentPath = getDirectoryPath(containingDirectory);
if (parentPath === containingDirectory) {
return undefined;
}
containingDirectory = parentPath;
}
} }
/** /**
@ -856,12 +812,26 @@ namespace ts {
} }
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled }; const state: ModuleResolutionState = { compilerOptions, host, traceEnabled };
const failedLookupLocations: string[] = []; const failedLookupLocations: string[] = [];
//const foo = combinePaths(combinePaths(globalCache, "node_modules"), "@types"); //neater //TODO: this could be DtsOnly but that would change baselines...
const resolved = tryInDirectory(Extensions.DtsOnly, globalCache, moduleName, failedLookupLocations, state); //fromFileOrDirectory(Extensions.DtsOnly, foo, moduleName, failedLookupLocations, state); //could just be from directory... //also, it used to look for js, but that's silly if we're installing @types!
//loadNodeModuleFromDirectory(Extensions.DtsOnly, candidate, failedLookupLocations, !directoryExists, state); const resolved = loadModuleFromSingleNodeModules(Extensions.TypeScript, moduleName, globalCache, failedLookupLocations, state);
//const resolved = loadModuleFromTypeRoots(state, moduleName, failedLookupLocations);
//const resolved = loadModuleFromNodeModules(Extensions.TypeScript, moduleName, globalCache, failedLookupLocations, state, /*checkOneLevel*/ true) ||
// loadModuleFromNodeModules(Extensions.JavaScript, moduleName, globalCache, failedLookupLocations, state, /*checkOneLevel*/ true);
return createResolvedModuleWithFailedLookupLocations(resolved, /*isExternalLibraryImport*/ true, failedLookupLocations); return createResolvedModuleWithFailedLookupLocations(resolved, /*isExternalLibraryImport*/ true, failedLookupLocations);
} }
/** Calls `callback` on `directory` and every ancestor directory it has, returning the first defined result. */
function forEachAncestorDirectory<T>(directory: string, callback: (directory: string) => T | undefined): T | undefined {
while (true) {
const result = callback(directory);
if (result !== undefined) {
return result;
}
const parentPath = getDirectoryPath(directory);
if (parentPath === directory) {
return undefined;
}
directory = parentPath;
}
}
} }

View file

@ -0,0 +1,11 @@
//// [tests/cases/conformance/moduleResolution/typeRoots_classic.ts] ////
//// [index.d.ts]
export function foo(): void;
//// [a.ts]
import { foo } from "foo";
//// [a.js]
"use strict";

View file

@ -0,0 +1,8 @@
=== /a.ts ===
import { foo } from "foo";
>foo : Symbol(foo, Decl(a.ts, 0, 8))
=== /types/foo/index.d.ts ===
export function foo(): void;
>foo : Symbol(foo, Decl(index.d.ts, 0, 0))

View file

@ -0,0 +1,22 @@
[
"======== Resolving module 'foo' from '/a.ts'. ========",
"Explicitly specified module resolution kind: 'Classic'.",
"File '/foo.ts' does not exist.",
"File '/foo.tsx' does not exist.",
"File '/foo.d.ts' does not exist.",
"File '/node_modules/@types/foo.ts' does not exist.",
"File '/node_modules/@types/foo.tsx' does not exist.",
"File '/node_modules/@types/foo.d.ts' does not exist.",
"File '/node_modules/@types/foo/package.json' does not exist.",
"File '/node_modules/@types/foo/index.ts' does not exist.",
"File '/node_modules/@types/foo/index.tsx' does not exist.",
"File '/node_modules/@types/foo/index.d.ts' does not exist.",
"File '/types/foo/package.json' does not exist.",
"File '/types/foo/index.d.ts' exist - use it as a name resolution result.",
"======== Module name 'foo' was successfully resolved to '/types/foo/index.d.ts'. ========",
"======== Resolving type reference directive 'foo', containing file '/__inferred type names__.ts', root directory '/types'. ========",
"Resolving with primary search path '/types'",
"File '/types/foo/package.json' does not exist.",
"File '/types/foo/index.d.ts' exist - use it as a name resolution result.",
"======== Type reference directive 'foo' was successfully resolved to '/types/foo/index.d.ts', primary: true. ========"
]

View file

@ -0,0 +1,8 @@
=== /a.ts ===
import { foo } from "foo";
>foo : () => void
=== /types/foo/index.d.ts ===
export function foo(): void;
>foo : () => void

View file

@ -0,0 +1,11 @@
//// [tests/cases/conformance/moduleResolution/typeRoots_node.ts] ////
//// [index.d.ts]
export function foo(): void;
//// [a.ts]
import { foo } from "foo";
//// [a.js]
"use strict";

View file

@ -0,0 +1,8 @@
=== /a.ts ===
import { foo } from "foo";
>foo : Symbol(foo, Decl(a.ts, 0, 8))
=== /types/foo/index.d.ts ===
export function foo(): void;
>foo : Symbol(foo, Decl(index.d.ts, 0, 0))

View file

@ -0,0 +1,28 @@
[
"======== Resolving module 'foo' from '/a.ts'. ========",
"Module resolution kind is not specified, using 'NodeJs'.",
"Loading module 'foo' from 'node_modules' folder.",
"File '/node_modules/foo.ts' does not exist.",
"File '/node_modules/foo.tsx' does not exist.",
"File '/node_modules/foo.d.ts' does not exist.",
"File '/node_modules/foo/package.json' does not exist.",
"File '/node_modules/foo/index.ts' does not exist.",
"File '/node_modules/foo/index.tsx' does not exist.",
"File '/node_modules/foo/index.d.ts' does not exist.",
"File '/node_modules/@types/foo.ts' does not exist.",
"File '/node_modules/@types/foo.tsx' does not exist.",
"File '/node_modules/@types/foo.d.ts' does not exist.",
"File '/node_modules/@types/foo/package.json' does not exist.",
"File '/node_modules/@types/foo/index.ts' does not exist.",
"File '/node_modules/@types/foo/index.tsx' does not exist.",
"File '/node_modules/@types/foo/index.d.ts' does not exist.",
"File '/types/foo/package.json' does not exist.",
"File '/types/foo/index.d.ts' exist - use it as a name resolution result.",
"Resolving real path for '/types/foo/index.d.ts', result '/types/foo/index.d.ts'",
"======== Module name 'foo' was successfully resolved to '/types/foo/index.d.ts'. ========",
"======== Resolving type reference directive 'foo', containing file '/__inferred type names__.ts', root directory '/types'. ========",
"Resolving with primary search path '/types'",
"File '/types/foo/package.json' does not exist.",
"File '/types/foo/index.d.ts' exist - use it as a name resolution result.",
"======== Type reference directive 'foo' was successfully resolved to '/types/foo/index.d.ts', primary: true. ========"
]

View file

@ -0,0 +1,8 @@
=== /a.ts ===
import { foo } from "foo";
>foo : () => void
=== /types/foo/index.d.ts ===
export function foo(): void;
>foo : () => void

View file

@ -0,0 +1,18 @@
// Identical to typeRoots_node except for following line
// @moduleResolution: classic
// @traceResolution: true
// @noImplicitReferences: true
// @currentDirectory: /
// @filename: /tsconfig.json
{
"compilerOptions": {
"typeRoots": ["types"]
}
}
// @filename: /types/foo/index.d.ts
export function foo(): void;
// @filename: /a.ts
import { foo } from "foo";

View file

@ -1,7 +1,6 @@
// @traceResolution: true // @traceResolution: true
// @noImplicitReferences: true // @noImplicitReferences: true
// @currentDirectory: / // @currentDirectory: /
//TODO: also want a test with "module": "node"
// @filename: /tsconfig.json // @filename: /tsconfig.json
{ {