diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 4ee8195cbd57c..9dd6db37790a0 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -995,7 +995,7 @@ namespace ts {
                 }
                 else {
                     forEach(options.lib, (libFileName, index) => {
-                        processRootFile(combinePaths(defaultLibraryPath, libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { kind: FileIncludeKind.LibFile, index });
+                        processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { kind: FileIncludeKind.LibFile, index });
                     });
                 }
             }
@@ -1737,7 +1737,7 @@ namespace ts {
                 return equalityComparer(file.fileName, getDefaultLibraryFileName());
             }
             else {
-                return some(options.lib, libFileName => equalityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName)));
+                return some(options.lib, libFileName => equalityComparer(file.fileName, pathForLibFile(libFileName)));
             }
         }
 
@@ -2406,7 +2406,7 @@ namespace ts {
             const libName = toFileNameLowerCase(ref.fileName);
             const libFileName = libMap.get(libName);
             if (libFileName) {
-                return getSourceFile(combinePaths(defaultLibraryPath, libFileName));
+                return getSourceFile(pathForLibFile(libFileName));
             }
         }
 
@@ -2883,13 +2883,32 @@ namespace ts {
             }
         }
 
+        function pathForLibFile(libFileName: string): string {
+            // Support resolving to lib.dom.d.ts -> @typescript/dom, and
+            //                      lib.dom.iterable.d.ts -> @typescript/dom/iterable
+            //                      lib.es2015.symbol.wellknown.d.ts -> @typescript/es2015/symbol-wellknown
+            const components = libFileName.split(".");
+            let path = components[1];
+            let i = 2;
+            while (components[i] && components[i] !== "d") {
+                path += (i === 2 ? "/" : "-") + components[i];
+                i++;
+            }
+            const resolveFrom = combinePaths(currentDirectory, `__lib_node_modules_lookup_${libFileName}__.ts`);
+            const localOverrideModuleResult = resolveModuleName("@typescript/" + path, resolveFrom, { moduleResolution: ModuleResolutionKind.NodeJs }, host, moduleResolutionCache);
+            if (localOverrideModuleResult?.resolvedModule) {
+                return localOverrideModuleResult.resolvedModule.resolvedFileName;
+            }
+            return combinePaths(defaultLibraryPath, libFileName);
+        }
+
         function processLibReferenceDirectives(file: SourceFile) {
             forEach(file.libReferenceDirectives, (libReference, index) => {
                 const libName = toFileNameLowerCase(libReference.fileName);
                 const libFileName = libMap.get(libName);
                 if (libFileName) {
                     // we ignore any 'no-default-lib' reference set on this file.
-                    processRootFile(combinePaths(defaultLibraryPath, libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ true, { kind: FileIncludeKind.LibReferenceDirective, file: file.path, index, });
+                    processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ true, { kind: FileIncludeKind.LibReferenceDirective, file: file.path, index, });
                 }
                 else {
                     const unqualifiedLibName = removeSuffix(removePrefix(libName, "lib."), ".d.ts");
diff --git a/tests/baselines/reference/libTypeScriptOverrideSimple.errors.txt b/tests/baselines/reference/libTypeScriptOverrideSimple.errors.txt
new file mode 100644
index 0000000000000..cf5912eb2769d
--- /dev/null
+++ b/tests/baselines/reference/libTypeScriptOverrideSimple.errors.txt
@@ -0,0 +1,14 @@
+tests/cases/compiler/index.ts(6,1): error TS2304: Cannot find name 'window'.
+
+
+==== /node_modules/@typescript/dom/index.d.ts (0 errors) ====
+    interface ABC { abc: string }
+==== tests/cases/compiler/index.ts (1 errors) ====
+    /// <reference lib="dom" />
+    const a: ABC = { abc: "Hello" }
+    
+    // This should fail because libdom has been replaced
+    // by the module above ^
+    window.localStorage
+    ~~~~~~
+!!! error TS2304: Cannot find name 'window'.
\ No newline at end of file
diff --git a/tests/baselines/reference/libTypeScriptOverrideSimple.js b/tests/baselines/reference/libTypeScriptOverrideSimple.js
new file mode 100644
index 0000000000000..ae95b842125f5
--- /dev/null
+++ b/tests/baselines/reference/libTypeScriptOverrideSimple.js
@@ -0,0 +1,18 @@
+//// [tests/cases/compiler/libTypeScriptOverrideSimple.ts] ////
+
+//// [index.d.ts]
+interface ABC { abc: string }
+//// [index.ts]
+/// <reference lib="dom" />
+const a: ABC = { abc: "Hello" }
+
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage
+
+//// [index.js]
+/// <reference lib="dom" />
+var a = { abc: "Hello" };
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage;
diff --git a/tests/baselines/reference/libTypeScriptOverrideSimple.symbols b/tests/baselines/reference/libTypeScriptOverrideSimple.symbols
new file mode 100644
index 0000000000000..37c7ca70cbe8d
--- /dev/null
+++ b/tests/baselines/reference/libTypeScriptOverrideSimple.symbols
@@ -0,0 +1,15 @@
+=== /node_modules/@typescript/dom/index.d.ts ===
+interface ABC { abc: string }
+>ABC : Symbol(ABC, Decl(index.d.ts, 0, 0))
+>abc : Symbol(ABC.abc, Decl(index.d.ts, 0, 15))
+
+=== tests/cases/compiler/index.ts ===
+/// <reference lib="dom" />
+const a: ABC = { abc: "Hello" }
+>a : Symbol(a, Decl(index.ts, 1, 5))
+>ABC : Symbol(ABC, Decl(index.d.ts, 0, 0))
+>abc : Symbol(abc, Decl(index.ts, 1, 16))
+
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage
diff --git a/tests/baselines/reference/libTypeScriptOverrideSimple.types b/tests/baselines/reference/libTypeScriptOverrideSimple.types
new file mode 100644
index 0000000000000..65a28d7093d1d
--- /dev/null
+++ b/tests/baselines/reference/libTypeScriptOverrideSimple.types
@@ -0,0 +1,19 @@
+=== /node_modules/@typescript/dom/index.d.ts ===
+interface ABC { abc: string }
+>abc : string
+
+=== tests/cases/compiler/index.ts ===
+/// <reference lib="dom" />
+const a: ABC = { abc: "Hello" }
+>a : ABC
+>{ abc: "Hello" } : { abc: string; }
+>abc : string
+>"Hello" : "Hello"
+
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage
+>window.localStorage : any
+>window : any
+>localStorage : any
+
diff --git a/tests/baselines/reference/libTypeScriptSubfileResolving.errors.txt b/tests/baselines/reference/libTypeScriptSubfileResolving.errors.txt
new file mode 100644
index 0000000000000..b2f731e2897da
--- /dev/null
+++ b/tests/baselines/reference/libTypeScriptSubfileResolving.errors.txt
@@ -0,0 +1,16 @@
+tests/cases/compiler/index.ts(6,1): error TS2304: Cannot find name 'window'.
+
+
+==== /node_modules/@typescript/dom/index.d.ts (0 errors) ====
+    // NOOP
+==== /node_modules/@typescript/dom/iterable.d.ts (0 errors) ====
+    interface DOMIterable { abc: string }
+==== tests/cases/compiler/index.ts (1 errors) ====
+    /// <reference lib="dom.iterable" />
+    const a: DOMIterable = { abc: "Hello" }
+    
+    // This should fail because libdom has been replaced
+    // by the module above ^
+    window.localStorage
+    ~~~~~~
+!!! error TS2304: Cannot find name 'window'.
\ No newline at end of file
diff --git a/tests/baselines/reference/libTypeScriptSubfileResolving.js b/tests/baselines/reference/libTypeScriptSubfileResolving.js
new file mode 100644
index 0000000000000..d975c3669c088
--- /dev/null
+++ b/tests/baselines/reference/libTypeScriptSubfileResolving.js
@@ -0,0 +1,20 @@
+//// [tests/cases/compiler/libTypeScriptSubfileResolving.ts] ////
+
+//// [index.d.ts]
+// NOOP
+//// [iterable.d.ts]
+interface DOMIterable { abc: string }
+//// [index.ts]
+/// <reference lib="dom.iterable" />
+const a: DOMIterable = { abc: "Hello" }
+
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage
+
+//// [index.js]
+/// <reference lib="dom.iterable" />
+var a = { abc: "Hello" };
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage;
diff --git a/tests/baselines/reference/libTypeScriptSubfileResolving.symbols b/tests/baselines/reference/libTypeScriptSubfileResolving.symbols
new file mode 100644
index 0000000000000..3bde25ae5b7e2
--- /dev/null
+++ b/tests/baselines/reference/libTypeScriptSubfileResolving.symbols
@@ -0,0 +1,17 @@
+=== /node_modules/@typescript/dom/index.d.ts ===
+// NOOP
+No type information for this code.=== /node_modules/@typescript/dom/iterable.d.ts ===
+interface DOMIterable { abc: string }
+>DOMIterable : Symbol(DOMIterable, Decl(iterable.d.ts, 0, 0))
+>abc : Symbol(DOMIterable.abc, Decl(iterable.d.ts, 0, 23))
+
+=== tests/cases/compiler/index.ts ===
+/// <reference lib="dom.iterable" />
+const a: DOMIterable = { abc: "Hello" }
+>a : Symbol(a, Decl(index.ts, 1, 5))
+>DOMIterable : Symbol(DOMIterable, Decl(iterable.d.ts, 0, 0))
+>abc : Symbol(abc, Decl(index.ts, 1, 24))
+
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage
diff --git a/tests/baselines/reference/libTypeScriptSubfileResolving.types b/tests/baselines/reference/libTypeScriptSubfileResolving.types
new file mode 100644
index 0000000000000..7fe3c02924cbc
--- /dev/null
+++ b/tests/baselines/reference/libTypeScriptSubfileResolving.types
@@ -0,0 +1,21 @@
+=== /node_modules/@typescript/dom/index.d.ts ===
+// NOOP
+No type information for this code.=== /node_modules/@typescript/dom/iterable.d.ts ===
+interface DOMIterable { abc: string }
+>abc : string
+
+=== tests/cases/compiler/index.ts ===
+/// <reference lib="dom.iterable" />
+const a: DOMIterable = { abc: "Hello" }
+>a : DOMIterable
+>{ abc: "Hello" } : { abc: string; }
+>abc : string
+>"Hello" : "Hello"
+
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage
+>window.localStorage : any
+>window : any
+>localStorage : any
+
diff --git a/tests/cases/compiler/libTypeScriptOverrideSimple.ts b/tests/cases/compiler/libTypeScriptOverrideSimple.ts
new file mode 100644
index 0000000000000..4ba67cd0c0181
--- /dev/null
+++ b/tests/cases/compiler/libTypeScriptOverrideSimple.ts
@@ -0,0 +1,9 @@
+// @Filename: /node_modules/@typescript/dom/index.d.ts
+interface ABC { abc: string }
+// @Filename: index.ts
+/// <reference lib="dom" />
+const a: ABC = { abc: "Hello" }
+
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage
\ No newline at end of file
diff --git a/tests/cases/compiler/libTypeScriptSubfileResolving.ts b/tests/cases/compiler/libTypeScriptSubfileResolving.ts
new file mode 100644
index 0000000000000..901d86a236aba
--- /dev/null
+++ b/tests/cases/compiler/libTypeScriptSubfileResolving.ts
@@ -0,0 +1,11 @@
+// @Filename: /node_modules/@typescript/dom/index.d.ts
+// NOOP
+// @Filename: /node_modules/@typescript/dom/iterable.d.ts
+interface DOMIterable { abc: string }
+// @Filename: index.ts
+/// <reference lib="dom.iterable" />
+const a: DOMIterable = { abc: "Hello" }
+
+// This should fail because libdom has been replaced
+// by the module above ^
+window.localStorage
\ No newline at end of file