Repository: parcel-bundler/parcel
Pull request #4624 (2020-05-18 22:44:37)

Enable flow's type-first mode
# ↪️ Pull Request

https://medium.com/flow-type/types-first-a-scalable-new-architecture-for-flow-3d8c7ba1d4eb

- Run `flow codemod annotate-exports ...`, cleanup and fixup the rest
- All private class properties have now a type declaration
- Changes to the typing:
	- Made `SharedReference` an opaque type (instead of number)
	- `cache.get<T>(key): Promise<?T>` instead of `any`

height[bot]: > Link [Height](https://parcel.height.app) tasks by mentioning a task ID in the pull request title or description, commit messages, or comments.
>
> You can also use "Close T-X" to automatically close a task when the pull request is merged.
parcel-benchmark: ## Benchmark Results
<details><summary>Kitchen Sink ✅</summary><p>

#### Timings

| Description | Time | Difference |
| --- | --- | --- |
| Cold | 6.22s | +198.00ms |
| Cached | 2.21s | +72.00ms |

#### Cold Bundles

| Bundle | Size | Difference | Time | Difference |
| --- | --- | --- | --- | --- |
| dist/legacy/parcel.d5807e82.webp | 102.94kb | +0.00b | 261.00ms | +114.00ms ⚠️ |
| dist/modern/parcel.d5807e82.webp | 102.94kb | +0.00b | 260.00ms | +114.00ms ⚠️ |
| dist/legacy/kitchen-sink.679578a5.js | 1.16kb | +0.00b | 1.66s | +276.00ms ⚠️ |
| dist/modern/kitchen-sink.90de237b.js | 1.16kb | +0.00b | 1.66s | +1.15s ⚠️ |
| dist/legacy/index.html | 709.00b | +0.00b | 656.00ms | +45.00ms ⚠️ |
| dist/modern/index.html | 709.00b | +0.00b | 654.00ms | +46.00ms ⚠️ |
| dist/legacy/styles.afb8e31a.css | 78.00b | +0.00b | 1.30s | -81.00ms 🚀 |
| dist/modern/styles.cda8c91b.css | 78.00b | +0.00b | 1.53s | +150.00ms ⚠️ |

#### Cached Bundles

| Bundle | Size | Difference | Time | Difference |
| --- | --- | --- | --- | --- |
| dist/legacy/parcel.d5807e82.webp | 102.94kb | +0.00b | 170.00ms | -12.00ms 🚀 |
| dist/modern/parcel.d5807e82.webp | 102.94kb | +0.00b | 170.00ms | -12.00ms 🚀 |

</p></details>

<details><summary>React HackerNews ✅</summary><p>

#### Timings

| Description | Time | Difference |
| --- | --- | --- |
| Cold | 9.86s | +743.00ms ⚠️ |
| Cached | 2.26s | +89.00ms |

#### Cold Bundles

| Bundle | Size | Difference | Time | Difference |
| --- | --- | --- | --- | --- |
| dist/main/index.js | 66.80kb | +0.00b | 2.31s | +164.00ms ⚠️ |
| dist/module/index.js | 37.47kb | +0.00b | 2.31s | +164.00ms ⚠️ |

#### Cached Bundles

| Bundle | Size | Difference | Time | Difference |
| --- | --- | --- | --- | --- |
| dist/main/index.js | 66.80kb | +0.00b | 243.00ms | +52.00ms ⚠️ |
| dist/module/index.js | 37.47kb | +0.00b | 237.00ms | +47.00ms ⚠️ |

</p></details>

<details><summary>AtlasKit Editor ✅</summary><p>

#### Timings

| Description | Time | Difference |
| --- | --- | --- |
| Cold | 2.80m | +1.89s |
| Cached | 5.24s | +59.00ms |

#### Cold Bundles

| Bundle | Size | Difference | Time | Difference |
| --- | --- | --- | --- | --- |
| dist/ak-editor.27263969.js | 2.50mb | -4.00b 🚀 | 1.63m | +1.94s |
| dist/pdfRenderer.74642224.js | 1.11mb | +3.00b ⚠️ | 57.66s | -1.58s |
| dist/Toolbar.4e6aa6b0.js | 100.36kb | +0.00b | 1.34m | +14.46s ⚠️ |
| dist/media-viewer.0b37a050.js | 71.13kb | +0.00b | 23.38s | +1.61s ⚠️ |
| dist/card.306e2acc.js | 66.70kb | +0.00b | 23.38s | -1.20m 🚀 |
| dist/component.7a54e3cc.js | 55.63kb | +0.00b | 6.95s | +1.13s ⚠️ |
| dist/Modal.83b93036.js | 41.59kb | +0.00b | 3.18s | -6.63s 🚀 |
| dist/component.4c8e3dd6.js | 29.13kb | +0.00b | 7.32s | -2.49s 🚀 |
| dist/DatePicker.d24458b4.js | 21.54kb | +0.00b | 9.44s | -3.97s 🚀 |
| dist/EmojiPickerComponent.a2474c55.js | 18.34kb | +0.00b | 51.27s | +39.18s ⚠️ |
| dist/clipboard.2b70f60b.js | 17.18kb | +0.00b | 1.63m | +33.33s ⚠️ |
| dist/js.baeda348.js | 16.46kb | +0.00b | 6.82s | +1.06s ⚠️ |
| dist/smartMediaEditor.ab4310d1.js | 14.62kb | +0.00b | 1.12m | -28.64s 🚀 |
| dist/ui.9e4d74b0.js | 14.45kb | +0.00b | 21.72s | -34.97s 🚀 |
| dist/workerHasher.ebf0b386.js | 11.83kb | +0.00b | 16.12s | -819.00ms 🚀 |
| dist/EmojiTypeAheadComponent.899f7d25.js | 9.20kb | +0.00b | 19.10s | -36.09s 🚀 |
| dist/media-viewer.52d4959e.js | 4.18kb | +0.00b | 34.94s | +13.10s ⚠️ |
| dist/EmojiPickerComponent.bd593806.js | 3.92kb | +0.00b | 51.27s | +39.07s ⚠️ |
| dist/16.cb2f1a3a.js | 3.72kb | +0.00b | 3.18s | +929.00ms ⚠️ |
| dist/Modal.1111ef83.js | 3.50kb | +0.00b | 3.18s | +929.00ms ⚠️ |
| dist/png-chunks-extract.c0f57e67.js | 3.49kb | +0.00b | 6.82s | +1.06s ⚠️ |
| dist/dropzone.79e05ece.js | 3.44kb | +0.00b | 1.63m | +38.63s ⚠️ |
| dist/16.c7be7376.js | 2.54kb | +0.00b | 6.81s | +1.06s ⚠️ |
| dist/EmojiUploadComponent.4946a1c6.js | 2.50kb | +0.00b | 51.27s | +39.07s ⚠️ |
| dist/ResourcedEmojiComponent.0979b683.js | 2.24kb | +0.00b | 7.27s | -2.50s 🚀 |
| dist/card.c002a0cc.js | 2.19kb | +0.00b | 57.77s | +21.09s ⚠️ |
| dist/16.bb063a1f.js | 1.83kb | +0.00b | 7.26s | +909.00ms ⚠️ |
| dist/media-picker-analytics-error-boundary.187d26a0.js | 1.82kb | +0.00b | 1.63m | +33.33s ⚠️ |
| dist/date.56d1aa9e.js | 1.81kb | +0.00b | 9.30s | +2.41s ⚠️ |
| dist/browser.90c1ebeb.js | 1.79kb | +0.00b | 1.12m | -28.66s 🚀 |
| dist/16.b1b0372d.js | 1.77kb | +0.00b | 7.09s | +1.15s ⚠️ |
| dist/images.16b3af40.js | 1.75kb | +0.00b | 7.56s | +513.00ms ⚠️ |
| dist/workerHasher.9975765a.js | 1.65kb | +0.00b | 16.00s | -931.00ms 🚀 |
| dist/ak-editor.7db5aa7b.js | 1.60kb | +0.00b | 1.34m | +14.44s ⚠️ |
| dist/list-number.d2097959.js | 1.54kb | +0.00b | 7.67s | +509.00ms ⚠️ |
| dist/status.f61d9ac5.js | 1.54kb | +0.00b | 7.86s | +427.00ms ⚠️ |
| dist/16.450f3a0d.js | 1.49kb | +0.00b | 7.25s | +1.10s ⚠️ |
| dist/code.4289d7dd.js | 1.46kb | +0.00b | 9.20s | +2.31s ⚠️ |
| dist/16.2b801dd1.js | 1.44kb | +0.00b | 7.08s | +1.14s ⚠️ |
| dist/16.fe51c023.js | 1.44kb | +0.00b | 7.10s | +1.05s ⚠️ |
| dist/16.7d4b2402.js | 1.42kb | +0.00b | 7.45s | +743.00ms ⚠️ |
| dist/link.36b44af7.js | 1.38kb | +0.00b | 7.60s | +477.00ms ⚠️ |
| dist/16.6b0e338c.js | 1.38kb | +0.00b | 7.45s | +929.00ms ⚠️ |
| dist/16.e32aa49c.js | 1.34kb | +0.00b | 3.18s | +929.00ms ⚠️ |
| dist/16.50f9c790.js | 1.33kb | +0.00b | 7.34s | +821.00ms ⚠️ |
| dist/emoji.3654aec7.js | 1.31kb | +0.00b | 7.56s | +513.00ms ⚠️ |
| dist/media-card-analytics-error-boundary.9ca79f13.js | 1.31kb | +0.00b | 1.05m | +26.16s ⚠️ |
| dist/16.81746ce1.js | 1.29kb | +0.00b | 7.44s | +928.00ms ⚠️ |
| dist/16.d1b58d7c.js | 1.29kb | +0.00b | 9.20s | +2.31s ⚠️ |
| dist/16.1dbb5df4.js | 1.28kb | +0.00b | 3.18s | +929.00ms ⚠️ |
| dist/Modal.6509cbe3.js | 1.26kb | +0.00b | 7.29s | +1.54s ⚠️ |
| dist/heading5.e338f1e8.js | 1.25kb | +0.00b | 8.36s | +422.00ms ⚠️ |
| dist/16.ceac57cd.js | 1.25kb | +0.00b | 7.25s | +1.10s ⚠️ |
| dist/expand.4d883914.js | 1.24kb | +0.00b | 8.36s | +418.00ms ⚠️ |
| dist/16.0efadc10.js | 1.23kb | +0.00b | 7.09s | +1.14s ⚠️ |
| dist/16.35be54a4.js | 1.23kb | +0.00b | 7.15s | +1.01s ⚠️ |
| dist/16.6be9bbc8.js | 1.23kb | +0.00b | 7.25s | +1.10s ⚠️ |
| dist/16.9015e8cf.js | 1.23kb | +0.00b | 6.82s | +895.00ms ⚠️ |
| dist/16.234ee133.js | 1.23kb | +0.00b | 7.27s | +5.02s ⚠️ |
| dist/16.7ca41ffe.js | 1.16kb | +0.00b | 7.45s | +929.00ms ⚠️ |
| dist/mention.ae379620.js | 1.15kb | +0.00b | 7.67s | +509.00ms ⚠️ |
| dist/heading4.b14d5ea4.js | 1.14kb | +0.00b | 8.02s | +401.00ms |
| dist/layout.d9df99ef.js | 1.13kb | +0.00b | 7.56s | +516.00ms ⚠️ |
| dist/divider.4476c3de.js | 1.11kb | +0.00b | 7.56s | +514.00ms ⚠️ |
| dist/quote.4733acb8.js | 1.10kb | +0.00b | 7.78s | +428.00ms ⚠️ |
| dist/action.b9409056.js | 1.08kb | +0.00b | 9.20s | +2.31s ⚠️ |
| dist/decision.77ee0aaa.js | 1.07kb | +0.00b | 7.50s | +521.00ms ⚠️ |
| dist/panel-warning.e55309d2.js | 1.06kb | +0.00b | 7.78s | +428.00ms ⚠️ |
| dist/list.cf500a90.js | 1.03kb | +0.00b | 7.67s | +509.00ms ⚠️ |
| dist/media-card-analytics-error-boundary.a014425d.js | 995.00b | +0.00b | 57.77s | +35.90s ⚠️ |
| dist/panel-error.364fbf3c.js | 987.00b | +0.00b | 7.67s | +509.00ms ⚠️ |
| dist/panel.e4fe05d1.js | 978.00b | +0.00b | 7.78s | +428.00ms ⚠️ |
| dist/panel-success.66723ab0.js | 926.00b | +0.00b | 7.79s | +437.00ms ⚠️ |
| dist/panel-note.a8b696c4.js | 922.00b | +0.00b | 7.72s | +456.00ms ⚠️ |
| dist/media-viewer-analytics-error-boundary.ee954f0e.js | 892.00b | +0.00b | 34.94s | +13.07s ⚠️ |
| dist/EmojiTypeAheadComponent.441c229c.js | 619.00b | +0.00b | 21.72s | -34.97s 🚀 |
| dist/simpleHasher.dd9d4306.js | 609.00b | +0.00b | 51.27s | +39.96s ⚠️ |
| dist/index.html | 219.00b | +0.00b | 892.00ms | -7.07s 🚀 |

#### Cached Bundles

*No bundle changes detected.*

</p></details>

<details><summary>Three.js x4 🚨</summary><p>

#### Timings

| Description | Time | Difference |
| --- | --- | --- |
| Cold | **FAILED** | -0.00ms |
| Cached | **FAILED** | -0.00ms |

#### Cold Bundles

*No bundles found, this is probably a failed build...*
#### Cached Bundles

*No bundles found, this is probably a failed build...*
</p></details>

**[Click here to view a detailed benchmark overview.](https://benchmark.parceljs.org/benchmark/265976904638530058)**
mischnic: It's probably easier to merge this after Maia's request PR. I'll just revert my changes on the conflicting files and run the codemod again.

Patch:
diff --git a/.flowconfig b/.flowconfig
index 5f2e47745..694c469bf 100644
--- a/.flowconfig
+++ b/.flowconfig
@@ -28,6 +28,8 @@ esproposal.nullish_coalescing=enable
 esproposal.optional_chaining=enable
 module.system.node.main_field=source
 module.system.node.main_field=main
+types_first=true
+well_formed_exports=true
 
 [strict]
 nonstrict-import
@@ -40,4 +42,4 @@ untyped-import
 untyped-type-import
 
 [version]
-0.124.0
+0.129.0
diff --git a/package.json b/package.json
index 566e6a1dc..4a4609ac6 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
     "cross-env": "^7.0.0",
     "doctoc": "^1.4.0",
     "eslint": "^6.0.0",
-    "flow-bin": "0.124.0",
+    "flow-bin": "0.129.0",
     "gulp": "^4.0.2",
     "gulp-babel": "^8.0.0",
     "lerna": "^3.3.2",
diff --git a/packages/bundlers/default/src/DefaultBundler.js b/packages/bundlers/default/src/DefaultBundler.js
index 09a9f3dff..e2c88a886 100644
--- a/packages/bundlers/default/src/DefaultBundler.js
+++ b/packages/bundlers/default/src/DefaultBundler.js
@@ -30,7 +30,7 @@ const HTTP_OPTIONS = {
   },
 };
 
-export default new Bundler({
+export default (new Bundler({
   // RULES:
   // 1. If dep.isAsync or dep.isEntry, start a new bundle group.
   // 2. If an asset is a different type than the current bundle, make a parallel bundle in the same bundle group.
@@ -470,7 +470,7 @@ export default new Bundler({
       }
     }
   },
-});
+}): Bundler);
 
 function deduplicate(bundleGraph: MutableBundleGraph) {
   bundleGraph.traverse(node => {
diff --git a/packages/core/cache/src/Cache.js b/packages/core/cache/src/Cache.js
index e5b85a0be..853df1fc3 100644
--- a/packages/core/cache/src/Cache.js
+++ b/packages/core/cache/src/Cache.js
@@ -45,16 +45,17 @@ export default class Cache {
     return this.fs.exists(this._getCachePath(key, '.blob'));
   }
 
-  getBlob(key: string, encoding?: buffer$Encoding) {
+  getBlob<T>(key: string, encoding?: buffer$Encoding): Promise<?T> {
+    // $FlowFixMe
     return this.fs.readFile(this._getCachePath(key, '.blob'), encoding);
   }
 
-  async setBlob(key: string, contents: Buffer | string) {
+  async setBlob(key: string, contents: Buffer | string): Promise<string> {
     await this.fs.writeFile(this._getCachePath(key, '.blob'), contents);
     return key;
   }
 
-  async get(key: string) {
+  async get<T>(key: string): Promise<?T> {
     try {
       let data = await this.fs.readFile(this._getCachePath(key));
       return deserialize(data);
@@ -67,7 +68,7 @@ export default class Cache {
     }
   }
 
-  async set(key: string, value: mixed) {
+  async set(key: string, value: mixed): Promise<?string> {
     try {
       let blobPath = this._getCachePath(key);
       let data = serialize(value);
diff --git a/packages/core/core/src/AssetGraph.js b/packages/core/core/src/AssetGraph.js
index cc5741f78..c32d62ade 100644
--- a/packages/core/core/src/AssetGraph.js
+++ b/packages/core/core/src/AssetGraph.js
@@ -10,6 +10,8 @@ import type {
   Dependency,
   DependencyNode,
   Entry,
+  EntryFileNode,
+  EntrySpecifierNode,
   Target,
 } from './types';
 
@@ -44,7 +46,7 @@ export function nodeFromDep(dep: Dependency): DependencyNode {
   };
 }
 
-export function nodeFromAssetGroup(assetGroup: AssetGroup) {
+export function nodeFromAssetGroup(assetGroup: AssetGroup): AssetGroupNode {
   return {
     id: md5FromObject({
       ...assetGroup,
@@ -56,7 +58,7 @@ export function nodeFromAssetGroup(assetGroup: AssetGroup) {
   };
 }
 
-export function nodeFromAsset(asset: Asset) {
+export function nodeFromAsset(asset: Asset): AssetNode {
   return {
     id: asset.id,
     type: 'asset',
@@ -64,7 +66,7 @@ export function nodeFromAsset(asset: Asset) {
   };
 }
 
-export function nodeFromEntrySpecifier(entry: string) {
+export function nodeFromEntrySpecifier(entry: string): EntrySpecifierNode {
   return {
     id: 'entry_specifier:' + entry,
     type: 'entry_specifier',
@@ -72,7 +74,7 @@ export function nodeFromEntrySpecifier(entry: string) {
   };
 }
 
-export function nodeFromEntryFile(entry: Entry) {
+export function nodeFromEntryFile(entry: Entry): EntryFileNode {
   return {
     id: 'entry_file:' + md5FromObject(entry),
     type: 'entry_file',
@@ -124,12 +126,12 @@ export default class AssetGraph extends Graph<AssetGraphNode> {
     this.replaceNodesConnectedTo(rootNode, nodes);
   }
 
-  addNode(node: AssetGraphNode) {
+  addNode(node: AssetGraphNode): AssetGraphNode {
     this.hash = null;
     return super.addNode(node);
   }
 
-  removeNode(node: AssetGraphNode) {
+  removeNode(node: AssetGraphNode): void {
     this.hash = null;
     this.onNodeRemoved && this.onNodeRemoved(node);
     return super.removeNode(node);
@@ -191,7 +193,7 @@ export default class AssetGraph extends Graph<AssetGraphNode> {
     this.replaceNodesConnectedTo(depNode, [nodeFromAssetGroup(assetGroup)]);
   }
 
-  shouldVisitChild(node: AssetGraphNode, childNode: AssetGraphNode) {
+  shouldVisitChild(node: AssetGraphNode, childNode: AssetGraphNode): boolean {
     if (
       node.type !== 'dependency' ||
       childNode.type !== 'asset_group' ||
@@ -255,7 +257,10 @@ export default class AssetGraph extends Graph<AssetGraphNode> {
   // using a wildcard and isn't an entry (in library mode).
   // This helps with performance building large libraries like `lodash-es`, which re-exports
   // a huge number of functions since we can avoid even transforming the files that aren't used.
-  shouldDeferDependency(dependency: Dependency, sideEffects: ?boolean) {
+  shouldDeferDependency(
+    dependency: Dependency,
+    sideEffects: ?boolean,
+  ): boolean {
     let defer = false;
     if (
       dependency.isWeak &&
@@ -402,7 +407,7 @@ export default class AssetGraph extends Graph<AssetGraphNode> {
     return entries;
   }
 
-  getHash() {
+  getHash(): string {
     if (this.hash != null) {
       return this.hash;
     }
diff --git a/packages/core/core/src/AssetGraphBuilder.js b/packages/core/core/src/AssetGraphBuilder.js
index 56aaae4b2..7174ba7e9 100644
--- a/packages/core/core/src/AssetGraphBuilder.js
+++ b/packages/core/core/src/AssetGraphBuilder.js
@@ -2,8 +2,8 @@
 
 import type {AbortSignal} from 'abortcontroller-polyfill/dist/cjs-ponyfill';
 import type {FilePath, ModuleSpecifier} from '@parcel/types';
-import type WorkerFarm, {Handle} from '@parcel/workers';
-import type {Event} from '@parcel/watcher';
+import type WorkerFarm, {Handle, SharedReference} from '@parcel/workers';
+import type {Event, Options as WatcherOptions} from '@parcel/watcher';
 import type {
   Asset,
   AssetGraphNode,
@@ -40,7 +40,7 @@ import dumpToGraphViz from './dumpGraphToGraphViz';
 
 type Opts = {|
   options: ParcelOptions,
-  optionsRef: number,
+  optionsRef: SharedReference,
   name: string,
   entries?: Array<string>,
   assetGroups?: Array<AssetGroup>,
@@ -64,7 +64,7 @@ export default class AssetGraphBuilder extends EventEmitter {
 
   changedAssets: Map<string, Asset> = new Map();
   options: ParcelOptions;
-  optionsRef: number;
+  optionsRef: SharedReference;
   workerFarm: WorkerFarm;
   cacheKey: string;
   entries: ?Array<string>;
@@ -234,7 +234,7 @@ export default class AssetGraphBuilder extends EventEmitter {
     await Promise.all(promises);
   }
 
-  shouldSkipRequest(node: AssetGraphNode) {
+  shouldSkipRequest(node: AssetGraphNode): boolean {
     return (
       node.complete === true ||
       !typesWithRequests.has(node.type) ||
@@ -244,7 +244,7 @@ export default class AssetGraphBuilder extends EventEmitter {
     );
   }
 
-  queueCorrespondingRequest(node: AssetGraphNode) {
+  queueCorrespondingRequest(node: AssetGraphNode): Promise<mixed> {
     switch (node.type) {
       case 'entry_specifier':
         return this.queue.add(() => this.runEntryRequest(node.value));
@@ -311,11 +311,11 @@ export default class AssetGraphBuilder extends EventEmitter {
     }
   }
 
-  respondToFSEvents(events: Array<Event>) {
+  respondToFSEvents(events: Array<Event>): boolean {
     return this.requestGraph.respondToFSEvents(events);
   }
 
-  getWatcherOptions() {
+  getWatcherOptions(): WatcherOptions {
     let vcsDirs = ['.git', '.hg'].map(dir =>
       path.join(this.options.projectRoot, dir),
     );
@@ -323,7 +323,11 @@ export default class AssetGraphBuilder extends EventEmitter {
     return {ignore};
   }
 
-  getCacheKeys() {
+  getCacheKeys(): {|
+    assetGraphKey: string,
+    requestGraphKey: string,
+    snapshotKey: string,
+  |} {
     let assetGraphKey = md5FromString(`${this.cacheKey}:assetGraph`);
     let requestGraphKey = md5FromString(`${this.cacheKey}:requestGraph`);
     let snapshotKey = md5FromString(`${this.cacheKey}:snapshot`);
@@ -336,8 +340,10 @@ export default class AssetGraphBuilder extends EventEmitter {
     }
 
     let {assetGraphKey, requestGraphKey, snapshotKey} = this.getCacheKeys();
-    let assetGraph = await this.options.cache.get(assetGraphKey);
-    let requestGraph = await this.options.cache.get(requestGraphKey);
+    let assetGraph = await this.options.cache.get<AssetGraph>(assetGraphKey);
+    let requestGraph = await this.options.cache.get<RequestGraph>(
+      requestGraphKey,
+    );
 
     if (assetGraph && requestGraph) {
       this.assetGraph = assetGraph;
diff --git a/packages/core/core/src/BundleGraph.js b/packages/core/core/src/BundleGraph.js
index 0ddc85c27..2961f5eed 100644
--- a/packages/core/core/src/BundleGraph.js
+++ b/packages/core/core/src/BundleGraph.js
@@ -3,6 +3,7 @@
 import type {
   BundleGroup,
   GraphVisitor,
+  SourceLocation,
   Symbol,
   TraversalActions,
 } from '@parcel/types';
@@ -40,6 +41,18 @@ type BundleGraphEdgeTypes =
   | 'references'
   | 'internal_async';
 
+type InternalSymbolResolution = {|
+  asset: Asset,
+  exportSymbol: string,
+  symbol: ?Symbol,
+  loc: ?SourceLocation,
+|};
+
+type InternalExportSymbolResolution = {|
+  ...InternalSymbolResolution,
+  +exportAs: Symbol | string,
+|};
+
 export default class BundleGraph {
   _assetPublicIds: Set<string>;
   _publicIdByAssetId: Map<string, string>;
@@ -614,7 +627,7 @@ export default class BundleGraph {
     });
   }
 
-  findReachableBundleWithAsset(bundle: Bundle, asset: Asset) {
+  findReachableBundleWithAsset(bundle: Bundle, asset: Asset): ?Bundle {
     let bundleGroups = this.getBundleGroupsContainingBundle(bundle);
 
     for (let bundleGroup of bundleGroups) {
@@ -863,7 +876,11 @@ export default class BundleGraph {
     );
   }
 
-  resolveSymbol(asset: Asset, symbol: Symbol, boundary: ?Bundle) {
+  resolveSymbol(
+    asset: Asset,
+    symbol: Symbol,
+    boundary: ?Bundle,
+  ): InternalSymbolResolution {
     let assetOutside = boundary && !this.bundleHasAsset(boundary, asset);
 
     let identifier = asset.symbols?.get(symbol)?.local;
@@ -992,7 +1009,7 @@ export default class BundleGraph {
     return publicId;
   }
 
-  getExportedSymbols(asset: Asset) {
+  getExportedSymbols(asset: Asset): Array<InternalExportSymbolResolution> {
     if (!asset.symbols) {
       return [];
     }
diff --git a/packages/core/core/src/BundlerRunner.js b/packages/core/core/src/BundlerRunner.js
index 5294dd2ec..d93f983c5 100644
--- a/packages/core/core/src/BundlerRunner.js
+++ b/packages/core/core/src/BundlerRunner.js
@@ -83,7 +83,9 @@ export default class BundlerRunner {
     let cacheKey;
     if (!this.options.disableCache) {
       cacheKey = await this.getCacheKey(graph, configResult);
-      let cachedBundleGraph = await this.options.cache.get(cacheKey);
+      let cachedBundleGraph = await this.options.cache.get<InternalBundleGraph>(
+        cacheKey,
+      );
       assertSignalNotAborted(signal);
 
       if (cachedBundleGraph) {
@@ -152,7 +154,10 @@ export default class BundlerRunner {
     return internalBundleGraph;
   }
 
-  async getCacheKey(assetGraph: AssetGraph, configResult: ?ConfigOutput) {
+  async getCacheKey(
+    assetGraph: AssetGraph,
+    configResult: ?ConfigOutput,
+  ): Promise<string> {
     let name = this.config.getBundlerName();
     let {version} = await this.config.getBundler();
 
diff --git a/packages/core/core/src/ConfigLoader.js b/packages/core/core/src/ConfigLoader.js
index eff6917ba..2101f95f4 100644
--- a/packages/core/core/src/ConfigLoader.js
+++ b/packages/core/core/src/ConfigLoader.js
@@ -38,7 +38,7 @@ export default class ConfigLoader {
     return promise;
   }
 
-  _load(configRequest: ConfigRequestDesc) {
+  _load(configRequest: ConfigRequestDesc): Promise<Config> {
     if (!configRequest.plugin) {
       return Promise.resolve().then(() => this.loadParcelConfig(configRequest));
     }
@@ -46,7 +46,7 @@ export default class ConfigLoader {
     return this.loadPluginConfig(configRequest);
   }
 
-  loadParcelConfig(configRequest: ConfigRequestDesc) {
+  loadParcelConfig(configRequest: ConfigRequestDesc): Config {
     let {filePath, isSource, env, pipeline, isURL} = configRequest;
     let dir = isSource ? path.dirname(filePath) : this.options.projectRoot;
     let searchPath = path.join(dir, 'index');
@@ -91,7 +91,7 @@ export default class ConfigLoader {
     isSource,
     filePath,
     meta: {parcelConfigPath},
-  }: ConfigRequestDesc) {
+  }: ConfigRequestDesc): Promise<Config> {
     let config = createConfig({
       isSource,
       searchPath: filePath,
diff --git a/packages/core/core/src/Environment.js b/packages/core/core/src/Environment.js
index 7190c04c3..dd7ad82ab 100644
--- a/packages/core/core/src/Environment.js
+++ b/packages/core/core/src/Environment.js
@@ -103,7 +103,7 @@ export function mergeEnvironments(
   });
 }
 
-export function getEnvironmentHash(env: Environment) {
+export function getEnvironmentHash(env: Environment): string {
   // context is excluded from hash so that assets can be shared between e.g. workers and browser.
   // Different engines should be sufficient to distinguish multi-target builds.
   return md5FromObject({
diff --git a/packages/core/core/src/Graph.js b/packages/core/core/src/Graph.js
index b3a4e2337..67d4a6edc 100644
--- a/packages/core/core/src/Graph.js
+++ b/packages/core/core/src/Graph.js
@@ -43,7 +43,9 @@ export default class Graph<TNode: Node, TEdgeType: string | null = null> {
     }
   }
 
-  static deserialize(opts: GraphOpts<TNode, TEdgeType>) {
+  static deserialize(
+    opts: GraphOpts<TNode, TEdgeType>,
+  ): Graph<TNode, TEdgeType> {
     return new this(opts);
   }
 
@@ -373,7 +375,7 @@ export default class Graph<TNode: Node, TEdgeType: string | null = null> {
     startNode: TNode,
     visit: GraphVisitor<TNode, TContext>,
     type: TEdgeType | null = null,
-  ) {
+  ): ?TContext {
     return this.dfs({
       visit,
       startNode,
diff --git a/packages/core/core/src/InternalConfig.js b/packages/core/core/src/InternalConfig.js
index a7e954b55..5a9f240a4 100644
--- a/packages/core/core/src/InternalConfig.js
+++ b/packages/core/core/src/InternalConfig.js
@@ -54,7 +54,13 @@ export function addDevDependency(
 }
 
 // TODO: start using edge types for more flexible invalidations
-export function getInvalidations(config: Config) {
+export function getInvalidations(
+  config: Config,
+): Array<
+  | {|action: 'add', pattern: Glob|}
+  | {|action: 'change', pattern: FilePath|}
+  | {|action: 'unlink', pattern: FilePath|},
+> {
   let invalidations = [];
 
   if (config.watchGlob != null) {
diff --git a/packages/core/core/src/PackagerRunner.js b/packages/core/core/src/PackagerRunner.js
index 29af585e3..895e2d497 100644
--- a/packages/core/core/src/PackagerRunner.js
+++ b/packages/core/core/src/PackagerRunner.js
@@ -10,12 +10,13 @@ import type {
   Async,
 } from '@parcel/types';
 import type SourceMap from '@parcel/source-map';
-import type WorkerFarm from '@parcel/workers';
+import type WorkerFarm, {SharedReference} from '@parcel/workers';
 import type {Bundle as InternalBundle, ParcelOptions, ReportFn} from './types';
 import type ParcelConfig from './ParcelConfig';
 import type InternalBundleGraph from './BundleGraph';
 import type {FileSystem, FileOptions} from '@parcel/fs';
 
+import invariant from 'assert';
 import {
   md5FromObject,
   md5FromString,
@@ -40,14 +41,14 @@ import {PARCEL_VERSION, HASH_REF_PREFIX, HASH_REF_REGEX} from './constants';
 
 type Opts = {|
   config: ParcelConfig,
-  configRef?: number,
+  configRef?: SharedReference,
   farm?: WorkerFarm,
   options: ParcelOptions,
-  optionsRef?: number,
+  optionsRef?: SharedReference,
   report: ReportFn,
 |};
 
-type BundleInfo = {|
+export type BundleInfo = {|
   +type: string,
   +size: number,
   +hash: string,
@@ -65,9 +66,9 @@ const BOUNDARY_LENGTH = HASH_REF_PREFIX.length + 32 - 1;
 
 export default class PackagerRunner {
   config: ParcelConfig;
-  configRef: ?number;
+  configRef: ?SharedReference;
   options: ParcelOptions;
-  optionsRef: ?number;
+  optionsRef: ?SharedReference;
   farm: ?WorkerFarm;
   pluginOptions: PluginOptions;
   distDir: FilePath;
@@ -75,10 +76,10 @@ export default class PackagerRunner {
   report: ReportFn;
   getBundleInfoFromWorker: ({|
     bundle: InternalBundle,
-    bundleGraphReference: number,
-    configRef: number,
+    bundleGraphReference: SharedReference,
+    configRef: SharedReference,
     cacheKeys: CacheKeyMap,
-    optionsRef: number,
+    optionsRef: SharedReference,
   |}) => Promise<BundleInfo>;
 
   constructor({config, configRef, farm, options, optionsRef, report}: Opts) {
@@ -142,7 +143,7 @@ export default class PackagerRunner {
   async processBundle(
     bundle: InternalBundle,
     bundleGraph: InternalBundleGraph,
-    bundleGraphReference: number,
+    bundleGraphReference: SharedReference,
   ): Promise<{|
     ...BundleInfo,
     cacheKeys: CacheKeyMap,
@@ -175,12 +176,12 @@ export default class PackagerRunner {
     };
   }
 
-  getBundleInfoFromCache(infoKey: string) {
+  getBundleInfoFromCache(infoKey: string): Async<?BundleInfo> {
     if (this.options.disableCache) {
       return;
     }
 
-    return this.options.cache.get(infoKey);
+    return this.options.cache.get<BundleInfo>(infoKey);
   }
 
   async getBundleInfo(
@@ -352,7 +353,10 @@ export default class PackagerRunner {
     return optimized;
   }
 
-  generateSourceMap(bundle: InternalBundle, map: SourceMap): Promise<string> {
+  async generateSourceMap(
+    bundle: InternalBundle,
+    map: SourceMap,
+  ): Promise<string> {
     // sourceRoot should be a relative path between outDir and rootDir for node.js targets
     let filePath = nullthrows(bundle.filePath);
     let sourceRoot: string = path.relative(
@@ -390,8 +394,7 @@ export default class PackagerRunner {
       bundle.isInline ||
       (bundle.target.sourceMap && bundle.target.sourceMap.inline);
 
-    // $FlowFixMe format is never object so it's always a string...
-    return map.stringify({
+    let stringified = await map.stringify({
       file: path.basename(mapFilename),
       // $FlowFixMe
       fs: this.options.inputFS,
@@ -402,6 +405,9 @@ export default class PackagerRunner {
       inlineSources,
       format: isInlineMap ? 'inline' : 'string',
     });
+
+    invariant(typeof stringified === 'string');
+    return stringified;
   }
 
   async getCacheKey(
diff --git a/packages/core/core/src/Parcel.js b/packages/core/core/src/Parcel.js
index 49881dbbd..1ce5677d8 100644
--- a/packages/core/core/src/Parcel.js
+++ b/packages/core/core/src/Parcel.js
@@ -10,10 +10,12 @@ import type {
   ModuleSpecifier,
   NamedBundle as INamedBundle,
 } from '@parcel/types';
-import type {ParcelOptions} from './types';
+import type {AssetRequestResult, ParcelOptions} from './types';
 import type {FarmOptions} from '@parcel/workers';
 import type {Diagnostic} from '@parcel/diagnostic';
 import type {AbortSignal} from 'abortcontroller-polyfill/dist/cjs-ponyfill';
+// eslint-disable-next-line no-unused-vars
+import type ParcelConfig from './ParcelConfig';
 
 import invariant from 'assert';
 import ThrowableDiagnostic, {anyToDiagnostic} from '@parcel/diagnostic';
@@ -40,24 +42,34 @@ import {PromiseQueue} from '@parcel/utils';
 
 registerCoreWithSerializer();
 
-export const INTERNAL_TRANSFORM = Symbol('internal_transform');
-export const INTERNAL_RESOLVE = Symbol('internal_resolve');
+export const INTERNAL_TRANSFORM: symbol = Symbol('internal_transform');
+export const INTERNAL_RESOLVE: symbol = Symbol('internal_resolve');
 
 export default class Parcel {
-  #assetGraphBuilder; // AssetGraphBuilder
-  #runtimesAssetGraphBuilder; // AssetGraphBuilder
-  #bundlerRunner; // BundlerRunner
-  #packagerRunner; // PackagerRunner
-  #config;
-  #farm; // WorkerFarm
-  #initialized = false; // boolean
-  #initialOptions; // InitialParcelOptions;
-  #reporterRunner; // ReporterRunner
-  #resolvedOptions = null; // ?ParcelOptions
-  #runPackage; // (bundle: IBundle, bundleGraph: InternalBundleGraph) => Promise<Stats>;
-  #watchAbortController; // AbortController
-  #watchQueue = new PromiseQueue<?BuildEvent>({maxConcurrent: 1}); // PromiseQueue<?BuildEvent>
-  #watchEvents = new ValueEmitter<
+  #assetGraphBuilder /*: AssetGraphBuilder*/;
+  #runtimesAssetGraphBuilder /*: AssetGraphBuilder*/;
+  #bundlerRunner /*: BundlerRunner*/;
+  #packagerRunner /*: PackagerRunner*/;
+  #config /*: ParcelConfig*/;
+  #farm /*: WorkerFarm*/;
+  #initialized /*: boolean*/ = false;
+  #initialOptions /*: InitialParcelOptions*/;
+  #reporterRunner /*: ReporterRunner*/;
+  #resolvedOptions /*: ?ParcelOptions*/ = null;
+  #watchAbortController /*: AbortController*/;
+  #watchQueue /*: PromiseQueue<?BuildEvent>*/ = new PromiseQueue<?BuildEvent>({
+    maxConcurrent: 1,
+  });
+  #watchEvents /*: ValueEmitter<
+    | {|
+        +error: Error,
+        +buildEvent?: void,
+      |}
+    | {|
+        +buildEvent: BuildEvent,
+        +error?: void,
+      |},
+  > */ = new ValueEmitter<
     | {|
         +error: Error,
         +buildEvent?: void,
@@ -67,8 +79,8 @@ export default class Parcel {
         +error?: void,
       |},
   >();
-  #watcherSubscription; // AsyncSubscription
-  #watcherCount = 0; // number
+  #watcherSubscription /*: ?AsyncSubscription*/;
+  #watcherCount /*: number*/ = 0;
 
   constructor(options: InitialParcelOptions) {
     this.#initialOptions = options;
@@ -142,7 +154,6 @@ export default class Parcel {
       report,
     });
 
-    this.#runPackage = this.#farm.createHandle('runPackage');
     this.#initialized = true;
   }
 
@@ -316,7 +327,7 @@ export default class Parcel {
     filePath: FilePath,
     env: EnvironmentOpts,
     code?: string,
-  |}) {
+  |}): Promise<AssetRequestResult> {
     let [result] = await Promise.all([
       this.#assetGraphBuilder.runTransform({
         filePath,
@@ -378,7 +389,7 @@ export default class Parcel {
   }
 
   // This is mainly for integration tests and it not public api!
-  _getResolvedParcelOptions() {
+  _getResolvedParcelOptions(): ParcelOptions {
     return nullthrows(
       this.#resolvedOptions,
       'Resolved options is null, please let parcel initialise before accessing this.',
@@ -394,7 +405,9 @@ export class BuildError extends ThrowableDiagnostic {
   }
 }
 
-export function createWorkerFarm(options: $Shape<FarmOptions> = {}) {
+export function createWorkerFarm(
+  options: $Shape<FarmOptions> = {},
+): WorkerFarm {
   return new WorkerFarm({
     ...options,
     workerPath: require.resolve('./worker'),
diff --git a/packages/core/core/src/ParcelConfig.js b/packages/core/core/src/ParcelConfig.js
index 5fa9b1e6a..ac6bfa8cc 100644
--- a/packages/core/core/src/ParcelConfig.js
+++ b/packages/core/core/src/ParcelConfig.js
@@ -69,7 +69,7 @@ export default class ParcelConfig {
     this.autoinstall = autoinstall;
   }
 
-  static deserialize(serialized: SerializedParcelConfig) {
+  static deserialize(serialized: SerializedParcelConfig): ParcelConfig {
     return new ParcelConfig(
       serialized.config,
       serialized.packageManager,
@@ -142,7 +142,7 @@ export default class ParcelConfig {
     );
   }
 
-  _getResolverNodes() {
+  _getResolverNodes(): PureParcelConfigPipeline {
     if (this.resolvers.length === 0) {
       throw new Error('No resolver plugins specified in .parcelrc config');
     }
@@ -154,7 +154,14 @@ export default class ParcelConfig {
     return this._getResolverNodes().map(r => r.packageName);
   }
 
-  getResolvers() {
+  getResolvers(): Promise<
+    Array<{|
+      name: string,
+      plugin: Resolver,
+      resolveFrom: FilePath,
+      version: Semver,
+    |}>,
+  > {
     return this.loadPlugins<Resolver>(this._getResolverNodes());
   }
 
@@ -172,7 +179,16 @@ export default class ParcelConfig {
     return validators.map(v => v.packageName);
   }
 
-  getValidators(filePath: FilePath) {
+  getValidators(
+    filePath: FilePath,
+  ): Promise<
+    Array<{|
+      name: string,
+      plugin: Validator,
+      resolveFrom: FilePath,
+      version: Semver,
+    |}>,
+  > {
     let validators = this._getValidatorNodes(filePath);
     return this.loadPlugins<Validator>(validators);
   }
@@ -221,7 +237,14 @@ export default class ParcelConfig {
     filePath: FilePath,
     pipeline?: ?string,
     allowEmpty?: boolean,
-  ) {
+  ): Promise<
+    Array<{|
+      name: string,
+      plugin: Transformer,
+      resolveFrom: FilePath,
+      version: Semver,
+    |}>,
+  > {
     return this.loadPlugins<Transformer>(
       this._getTransformerNodes(filePath, pipeline, allowEmpty),
     );
@@ -243,7 +266,14 @@ export default class ParcelConfig {
     return this.loadPlugin<Bundler>(this.bundler);
   }
 
-  getNamers() {
+  getNamers(): Promise<
+    Array<{|
+      name: string,
+      plugin: Namer,
+      resolveFrom: FilePath,
+      version: Semver,
+    |}>,
+  > {
     if (this.namers.length === 0) {
       throw new Error('No namer plugins specified in .parcelrc config');
     }
@@ -298,7 +328,10 @@ export default class ParcelConfig {
     };
   }
 
-  _getOptimizerNodes(filePath: FilePath, pipeline: ?string) {
+  _getOptimizerNodes(
+    filePath: FilePath,
+    pipeline: ?string,
+  ): PureParcelConfigPipeline {
     return (
       this.matchGlobMapPipelines(filePath, this.optimizers, pipeline) ?? []
     );
@@ -328,11 +361,18 @@ export default class ParcelConfig {
     return this.loadPlugins<Optimizer>(optimizers);
   }
 
-  getReporters() {
+  getReporters(): Promise<
+    Array<{|
+      name: string,
+      plugin: Reporter,
+      resolveFrom: FilePath,
+      version: Semver,
+    |}>,
+  > {
     return this.loadPlugins<Reporter>(this.reporters);
   }
 
-  isGlobMatch(filePath: FilePath, pattern: Glob, pipeline?: ?string) {
+  isGlobMatch(filePath: FilePath, pattern: Glob, pipeline?: ?string): boolean {
     let prefix = pipeline ? `${pipeline}:` : '';
     return (
       isMatch(prefix + filePath, pattern) ||
@@ -340,7 +380,7 @@ export default class ParcelConfig {
     );
   }
 
-  matchGlobMap(filePath: FilePath, globMap: {[Glob]: any, ...}) {
+  matchGlobMap<T>(filePath: FilePath, globMap: {|[Glob]: T|}): ?T {
     for (let pattern in globMap) {
       if (this.isGlobMatch(filePath, pattern)) {
         return globMap[pattern];
@@ -352,7 +392,7 @@ export default class ParcelConfig {
 
   matchGlobMapPipelines(
     filePath: FilePath,
-    globMap: {[Glob]: ExtendableParcelConfigPipeline, ...},
+    globMap: {|[Glob]: ExtendableParcelConfigPipeline|},
     pipeline?: ?string,
   ): PureParcelConfigPipeline {
     let matches = [];
diff --git a/packages/core/core/src/ParcelConfig.schema.js b/packages/core/core/src/ParcelConfig.schema.js
index 1d5069dd7..eb224f196 100644
--- a/packages/core/core/src/ParcelConfig.schema.js
+++ b/packages/core/core/src/ParcelConfig.schema.js
@@ -50,7 +50,7 @@ const validatePluginName = (pluginType: string, key: string) => {
   };
 };
 
-const validateExtends = (val: string) => {
+const validateExtends = (val: string): void => {
   // allow relative paths...
   if (val.startsWith('.')) return;
 
@@ -110,16 +110,21 @@ export default {
     },
     bundler: {
       type: 'string',
-      __validate: validatePluginName('bundler', 'bundler'),
+      __validate: (validatePluginName('bundler', 'bundler'): (
+        val: string,
+      ) => void),
     },
-    resolvers: pipelineSchema('resolver', 'resolvers'),
-    transformers: mapPipelineSchema('transformer', 'transformers'),
-    validators: mapPipelineSchema('validator', 'validators'),
-    namers: pipelineSchema('namer', 'namers'),
-    packagers: mapStringSchema('packager', 'packagers'),
-    optimizers: mapPipelineSchema('optimizer', 'optimizers'),
-    reporters: pipelineSchema('reporter', 'reporters'),
-    runtimes: mapPipelineSchema('runtime', 'runtimes'),
+    resolvers: (pipelineSchema('resolver', 'resolvers'): SchemaEntity),
+    transformers: (mapPipelineSchema(
+      'transformer',
+      'transformers',
+    ): SchemaEntity),
+    validators: (mapPipelineSchema('validator', 'validators'): SchemaEntity),
+    namers: (pipelineSchema('namer', 'namers'): SchemaEntity),
+    packagers: (mapStringSchema('packager', 'packagers'): SchemaEntity),
+    optimizers: (mapPipelineSchema('optimizer', 'optimizers'): SchemaEntity),
+    reporters: (pipelineSchema('reporter', 'reporters'): SchemaEntity),
+    runtimes: (mapPipelineSchema('runtime', 'runtimes'): SchemaEntity),
     filePath: {
       type: 'string',
     },
diff --git a/packages/core/core/src/RequestTracker.js b/packages/core/core/src/RequestTracker.js
index d54283204..fe25a55f0 100644
--- a/packages/core/core/src/RequestTracker.js
+++ b/packages/core/core/src/RequestTracker.js
@@ -97,7 +97,7 @@ export class RequestGraph extends Graph<
   unpredicatableNodeIds: Set<NodeId> = new Set();
 
   // $FlowFixMe
-  static deserialize(opts: SerializedRequestGraph) {
+  static deserialize(opts: SerializedRequestGraph): RequestGraph {
     // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381
     let deserialized = new RequestGraph(opts);
     deserialized.invalidNodeIds = opts.invalidNodeIds;
@@ -119,7 +119,7 @@ export class RequestGraph extends Graph<
     };
   }
 
-  addNode(node: RequestGraphNode) {
+  addNode(node: RequestGraphNode): RequestGraphNode {
     if (!this.hasNode(node.id)) {
       if (node.type === 'glob') {
         this.globNodeIds.add(node.id);
@@ -129,7 +129,7 @@ export class RequestGraph extends Graph<
     return super.addNode(node);
   }
 
-  removeNode(node: RequestGraphNode) {
+  removeNode(node: RequestGraphNode): void {
     this.invalidNodeIds.delete(node.id);
     this.incompleteNodeIds.delete(node.id);
     if (node.type === 'glob') {
@@ -138,7 +138,9 @@ export class RequestGraph extends Graph<
     return super.removeNode(node);
   }
 
-  getRequestNode(id: string) {
+  getRequestNode(
+    id: string,
+  ): {|id: string, +type: 'request', value: StoredRequest|} {
     let node = nullthrows(this.getNode(id));
     invariant(node.type === 'request');
     return node;
@@ -324,7 +326,7 @@ export default class RequestTracker {
     }
   }
 
-  hasValidResult(id: string) {
+  hasValidResult(id: string): boolean {
     return (
       this.graph.nodes.has(id) &&
       !this.graph.invalidNodeIds.has(id) &&
@@ -356,7 +358,7 @@ export default class RequestTracker {
     return this.graph.respondToFSEvents(events);
   }
 
-  hasInvalidRequests() {
+  hasInvalidRequests(): boolean {
     return this.graph.invalidNodeIds.size > 0;
   }
 
diff --git a/packages/core/core/src/Transformation.js b/packages/core/core/src/Transformation.js
index 0a528c963..e7d081d09 100644
--- a/packages/core/core/src/Transformation.js
+++ b/packages/core/core/src/Transformation.js
@@ -55,6 +55,11 @@ export type TransformationOpts = {|
   workerApi: WorkerApi,
 |};
 
+export type TransformationResult = {|
+  assets: Array<AssetValue>,
+  configRequests: Array<ConfigRequestAndResult>,
+|};
+
 type ConfigMap = Map<PackageName, Config>;
 type ConfigRequestAndResult = {|
   request: ConfigRequestDesc,
@@ -91,16 +96,13 @@ export default class Transformation {
     this.impactfulOptions = {hot};
   }
 
-  async loadConfig(configRequest: ConfigRequestDesc) {
+  async loadConfig(configRequest: ConfigRequestDesc): Promise<Config> {
     let result = await this.configLoader.load(configRequest);
     this.configRequests.push({request: configRequest, result});
     return result;
   }
 
-  async run(): Promise<{|
-    assets: Array<AssetValue>,
-    configRequests: Array<ConfigRequestAndResult>,
-  |}> {
+  async run(): Promise<TransformationResult> {
     await initSourcemaps;
 
     this.report({
@@ -333,14 +335,14 @@ export default class Transformation {
     return finalAssets.concat(resultingAssets);
   }
 
-  async readFromCache(
-    cacheKey: string,
-  ): Promise<null | Array<UncommittedAsset>> {
+  async readFromCache(cacheKey: string): Promise<?Array<UncommittedAsset>> {
     if (this.options.disableCache || this.request.code != null) {
       return null;
     }
 
-    let cachedAssets = await this.options.cache.get(cacheKey);
+    let cachedAssets = await this.options.cache.get<Array<AssetValue>>(
+      cacheKey,
+    );
     if (!cachedAssets) {
       return null;
     }
diff --git a/packages/core/core/src/UncommittedAsset.js b/packages/core/core/src/UncommittedAsset.js
index 4d9d09be4..bd2fd2c95 100644
--- a/packages/core/core/src/UncommittedAsset.js
+++ b/packages/core/core/src/UncommittedAsset.js
@@ -229,7 +229,7 @@ export default class UncommittedAsset {
     );
   }
 
-  addDependency(opts: DependencyOptions) {
+  addDependency(opts: DependencyOptions): string {
     // eslint-disable-next-line no-unused-vars
     let {env, target, symbols, ...rest} = opts;
     let dep = createDependency({
diff --git a/packages/core/core/src/constants.js b/packages/core/core/src/constants.js
index 0c0b759e9..28d366222 100644
--- a/packages/core/core/src/constants.js
+++ b/packages/core/core/src/constants.js
@@ -5,4 +5,7 @@ import {version} from '../package.json';
 
 export const PARCEL_VERSION = version;
 export const HASH_REF_PREFIX = 'HASH_REF_';
-export const HASH_REF_REGEX = new RegExp(`${HASH_REF_PREFIX}\\w{32}`, 'g');
+export const HASH_REF_REGEX: RegExp = new RegExp(
+  `${HASH_REF_PREFIX}\\w{32}`,
+  'g',
+);
diff --git a/packages/core/core/src/public/Asset.js b/packages/core/core/src/public/Asset.js
index 7ba3b583f..a5cb8d433 100644
--- a/packages/core/core/src/public/Asset.js
+++ b/packages/core/core/src/public/Asset.js
@@ -61,7 +61,10 @@ export function mutableAssetToUncommittedAsset(
   return nullthrows(_mutableAssetToUncommittedAsset.get(mutableAsset));
 }
 
-export function assetFromValue(value: AssetValue, options: ParcelOptions) {
+export function assetFromValue(
+  value: AssetValue,
+  options: ParcelOptions,
+): Asset {
   return new Asset(
     value.committed
       ? new CommittedAsset(value, options)
@@ -73,7 +76,7 @@ export function assetFromValue(value: AssetValue, options: ParcelOptions) {
 }
 
 class BaseAsset {
-  #asset; // CommittedAsset | UncommittedAsset
+  #asset: CommittedAsset | UncommittedAsset;
 
   constructor(asset: CommittedAsset | UncommittedAsset) {
     this.#asset = asset;
@@ -81,7 +84,7 @@ class BaseAsset {
   }
 
   // $FlowFixMe
-  [inspect]() {
+  [inspect](): string {
     return `Asset(${this.filePath})`;
   }
 
@@ -193,9 +196,9 @@ class BaseAsset {
 }
 
 export class Asset extends BaseAsset implements IAsset {
-  #asset; // InternalAsset
+  #asset /*: CommittedAsset | UncommittedAsset */;
 
-  constructor(asset: CommittedAsset | UncommittedAsset) {
+  constructor(asset: CommittedAsset | UncommittedAsset): Asset {
     let existing = assetValueToAsset.get(asset.value);
     if (existing != null) {
       return existing;
@@ -204,6 +207,7 @@ export class Asset extends BaseAsset implements IAsset {
     super(asset);
     this.#asset = asset;
     assetValueToAsset.set(asset.value, this);
+    return this;
   }
 
   get stats(): Stats {
@@ -212,9 +216,9 @@ export class Asset extends BaseAsset implements IAsset {
 }
 
 export class MutableAsset extends BaseAsset implements IMutableAsset {
-  #asset; // InternalAsset
+  #asset /*: UncommittedAsset */;
 
-  constructor(asset: UncommittedAsset) {
+  constructor(asset: UncommittedAsset): MutableAsset {
     let existing = assetValueToMutableAsset.get(asset.value);
     if (existing != null) {
       return existing;
@@ -224,6 +228,7 @@ export class MutableAsset extends BaseAsset implements IMutableAsset {
     this.#asset = asset;
     assetValueToMutableAsset.set(asset.value, this);
     _mutableAssetToUncommittedAsset.set(this, asset);
+    return this;
   }
 
   setMap(map: ?SourceMap): void {
diff --git a/packages/core/core/src/public/Bundle.js b/packages/core/core/src/public/Bundle.js
index 9b725a262..0280653b2 100644
--- a/packages/core/core/src/public/Bundle.js
+++ b/packages/core/core/src/public/Bundle.js
@@ -53,9 +53,9 @@ export function bundleToInternalBundleGraph(bundle: IBundle): BundleGraph {
 let _private = {};
 
 export class Bundle implements IBundle {
-  #bundle; // InternalBundle
-  #bundleGraph; // BundleGraph
-  #options; // ParcelOptions
+  #bundle /*: InternalBundle */;
+  #bundleGraph /*: BundleGraph */;
+  #options /*: ParcelOptions */;
 
   constructor(
     sentinel: mixed,
@@ -178,7 +178,7 @@ export class Bundle implements IBundle {
     );
   }
 
-  traverseAssets<TContext>(visit: GraphVisitor<IAsset, TContext>) {
+  traverseAssets<TContext>(visit: GraphVisitor<IAsset, TContext>): ?TContext {
     return this.#bundleGraph.traverseAssets(
       this.#bundle,
       mapVisitor(asset => assetFromValue(asset, this.#options), visit),
@@ -187,8 +187,8 @@ export class Bundle implements IBundle {
 }
 
 export class NamedBundle extends Bundle implements INamedBundle {
-  #bundle; // InternalBundle
-  #bundleGraph; // BundleGraph
+  #bundle /*: InternalBundle */;
+  #bundleGraph /*: BundleGraph */;
 
   constructor(
     sentinel: mixed,
diff --git a/packages/core/core/src/public/Config.js b/packages/core/core/src/public/Config.js
index 8de119eda..36cdcacf8 100644
--- a/packages/core/core/src/public/Config.js
+++ b/packages/core/core/src/public/Config.js
@@ -2,6 +2,7 @@
 // flowlint unsafe-getters-setters:off
 import type {
   Config as IConfig,
+  ConfigResult,
   FilePath,
   Glob,
   PackageJSON,
@@ -20,10 +21,10 @@ const internalConfigToConfig: DefaultWeakMap<
 > = new DefaultWeakMap(() => new WeakMap());
 
 export default class PublicConfig implements IConfig {
-  #config; // Config;
-  #options; // ParcelOptions
+  #config /*: Config */;
+  #options /*: ParcelOptions */;
 
-  constructor(config: Config, options: ParcelOptions) {
+  constructor(config: Config, options: ParcelOptions): PublicConfig {
     let existing = internalConfigToConfig.get(options).get(config);
     if (existing != null) {
       return existing;
@@ -32,30 +33,31 @@ export default class PublicConfig implements IConfig {
     this.#config = config;
     this.#options = options;
     internalConfigToConfig.get(options).set(config, this);
+    return this;
   }
 
-  get env() {
+  get env(): Environment {
     return new Environment(this.#config.env);
   }
 
-  get searchPath() {
+  get searchPath(): FilePath {
     return this.#config.searchPath;
   }
 
-  get result() {
+  get result(): ConfigResult {
     return this.#config.result;
   }
 
-  get isSource() {
+  get isSource(): boolean {
     return this.#config.isSource;
   }
 
-  get includedFiles() {
+  get includedFiles(): Set<FilePath> {
     return this.#config.includedFiles;
   }
 
   // $FlowFixMe
-  setResult(result: any) {
+  setResult(result: any): void {
     this.#config.result = result;
   }
 
diff --git a/packages/core/core/src/public/Dependency.js b/packages/core/core/src/public/Dependency.js
index d4cad06b3..c7d6fa5a5 100644
--- a/packages/core/core/src/public/Dependency.js
+++ b/packages/core/core/src/public/Dependency.js
@@ -30,9 +30,9 @@ export function dependencyToInternalDependency(
 }
 
 export default class Dependency implements IDependency {
-  #dep; // InternalDependency
+  #dep /*: InternalDependency */;
 
-  constructor(dep: InternalDependency) {
+  constructor(dep: InternalDependency): Dependency {
     let existing = internalDependencyToDependency.get(dep);
     if (existing != null) {
       return existing;
@@ -41,10 +41,11 @@ export default class Dependency implements IDependency {
     this.#dep = dep;
     _dependencyToInternalDependency.set(this, dep);
     internalDependencyToDependency.set(dep, this);
+    return this;
   }
 
   // $FlowFixMe
-  [inspect]() {
+  [inspect](): string {
     return `Dependency(${String(this.sourcePath)} -> ${this.moduleSpecifier})`;
   }
 
diff --git a/packages/core/core/src/public/Environment.js b/packages/core/core/src/public/Environment.js
index 70031e21b..b4e4223cd 100644
--- a/packages/core/core/src/public/Environment.js
+++ b/packages/core/core/src/public/Environment.js
@@ -12,7 +12,7 @@ import nullthrows from 'nullthrows';
 import browserslist from 'browserslist';
 import semver from 'semver';
 
-export const BROWSER_ENVS = new Set<string>([
+export const BROWSER_ENVS: Set<string> = new Set<string>([
   'browser',
   'web-worker',
   'service-worker',
@@ -72,9 +72,9 @@ export function environmentToInternalEnvironment(
 }
 
 export default class Environment implements IEnvironment {
-  #environment; // InternalEnvironment
+  #environment /*: InternalEnvironment */;
 
-  constructor(env: InternalEnvironment) {
+  constructor(env: InternalEnvironment): Environment {
     let existing = internalEnvironmentToEnvironment.get(env);
     if (existing != null) {
       return existing;
@@ -83,6 +83,7 @@ export default class Environment implements IEnvironment {
     this.#environment = env;
     _environmentToInternalEnvironment.set(this, env);
     internalEnvironmentToEnvironment.set(env, this);
+    return this;
   }
 
   get context(): EnvironmentContext {
@@ -116,27 +117,27 @@ export default class Environment implements IEnvironment {
     return this.#environment.scopeHoist;
   }
 
-  isBrowser() {
+  isBrowser(): boolean {
     return BROWSER_ENVS.has(this.#environment.context);
   }
 
-  isNode() {
+  isNode(): boolean {
     return NODE_ENVS.has(this.#environment.context);
   }
 
-  isElectron() {
+  isElectron(): boolean {
     return ELECTRON_ENVS.has(this.#environment.context);
   }
 
-  isIsolated() {
+  isIsolated(): boolean {
     return ISOLATED_ENVS.has(this.#environment.context);
   }
 
-  isWorker() {
+  isWorker(): boolean {
     return WORKER_ENVS.has(this.#environment.context);
   }
 
-  matchesEngines(minVersions: VersionMap) {
+  matchesEngines(minVersions: VersionMap): boolean {
     // Determine if the environment matches some minimum version requirements.
     // For browsers, we run a browserslist query with and without the minimum
     // required browsers and compare the lists. For node, we just check semver.
diff --git a/packages/core/core/src/public/MutableBundleGraph.js b/packages/core/core/src/public/MutableBundleGraph.js
index 32704279f..6bed7a113 100644
--- a/packages/core/core/src/public/MutableBundleGraph.js
+++ b/packages/core/core/src/public/MutableBundleGraph.js
@@ -29,9 +29,9 @@ import {HASH_REF_PREFIX} from '../constants';
 
 export default class MutableBundleGraph extends BundleGraph<IBundle>
   implements IMutableBundleGraph {
-  #graph; // InternalBundleGraph
-  #options; // ParcelOptions
-  #bundlePublicIds = new Set<string>();
+  #graph /*: InternalBundleGraph */;
+  #options /*: ParcelOptions */;
+  #bundlePublicIds /*: Set<string> */ = new Set<string>();
 
   constructor(graph: InternalBundleGraph, options: ParcelOptions) {
     super(graph, Bundle.get, options);
diff --git a/packages/core/core/src/public/PluginOptions.js b/packages/core/core/src/public/PluginOptions.js
index 41f0faba2..42858a058 100644
--- a/packages/core/core/src/public/PluginOptions.js
+++ b/packages/core/core/src/public/PluginOptions.js
@@ -18,9 +18,9 @@ let parcelOptionsToPluginOptions: WeakMap<
 > = new WeakMap();
 
 export default class PluginOptions implements IPluginOptions {
-  #options; // ParcelOptions
+  #options /*: ParcelOptions */;
 
-  constructor(options: ParcelOptions) {
+  constructor(options: ParcelOptions): PluginOptions {
     let existing = parcelOptionsToPluginOptions.get(options);
     if (existing != null) {
       return existing;
@@ -28,6 +28,7 @@ export default class PluginOptions implements IPluginOptions {
 
     this.#options = options;
     parcelOptionsToPluginOptions.set(options, this);
+    return this;
   }
 
   get instanceId(): string {
diff --git a/packages/core/core/src/public/Symbols.js b/packages/core/core/src/public/Symbols.js
index 96d4fec8b..a99a891d9 100644
--- a/packages/core/core/src/public/Symbols.js
+++ b/packages/core/core/src/public/Symbols.js
@@ -21,9 +21,9 @@ export class Symbols implements ISymbols {
   /*::
   @@iterator(): Iterator<[Symbol, {|local: Symbol, loc: ?SourceLocation|}]> { return ({}: any); }
   */
-  #value; // Asset
+  #value /*: Asset */;
 
-  constructor(asset: Asset) {
+  constructor(asset: Asset): Symbols {
     let existing = valueToSymbols.get(asset);
     if (existing != null) {
       return existing;
@@ -31,6 +31,7 @@ export class Symbols implements ISymbols {
 
     this.#value = asset;
     valueToSymbols.set(asset, this);
+    return this;
   }
 
   get(exportSymbol: Symbol): ?{|local: Symbol, loc: ?SourceLocation|} {
@@ -51,13 +52,13 @@ export class Symbols implements ISymbols {
   }
 
   // $FlowFixMe
-  [Symbol.iterator]() {
+  [Symbol.iterator](): any {
     return this.#value.symbols
       ? this.#value.symbols[Symbol.iterator]()
       : EMPTY_ITERATOR;
   }
 
-  get isCleared() {
+  get isCleared(): boolean {
     return this.#value.symbols == null;
   }
 }
@@ -71,7 +72,7 @@ class MutableSymbols {
   /*::
   @@iterator(): Iterator<[Symbol, {|local: Symbol, loc: ?SourceLocation|}]> { return ({}: any); }
   */
-  #value; // Asset
+  #value: Asset | Dependency;
 
   constructor(asset: Asset | Dependency) {
     this.#value = asset;
@@ -102,21 +103,21 @@ class MutableSymbols {
   }
 
   // $FlowFixMe
-  [Symbol.iterator]() {
+  [Symbol.iterator](): any {
     return this.#value.symbols
       ? this.#value.symbols[Symbol.iterator]()
       : EMPTY_ITERATOR;
   }
 
-  get isCleared() {
+  get isCleared(): boolean {
     return this.#value.symbols == null;
   }
 }
 
 export class MutableDependencySymbols extends MutableSymbols
   implements IMutableSymbols {
-  #dependency; // Dependency
-  constructor(dependency: Dependency) {
+  #dependency: Dependency;
+  constructor(dependency: Dependency): MutableDependencySymbols {
     let existing = valueToMutableSymbols.get(dependency);
     if (existing != null) {
       return ((existing: any): MutableDependencySymbols);
@@ -124,6 +125,7 @@ export class MutableDependencySymbols extends MutableSymbols
 
     super(dependency);
     this.#dependency = dependency;
+    return this;
   }
 
   clear() {
@@ -133,8 +135,8 @@ export class MutableDependencySymbols extends MutableSymbols
 
 export class MutableAssetSymbols extends MutableSymbols
   implements IMutableSymbols {
-  #asset; // Asset
-  constructor(asset: Asset) {
+  #asset: Asset;
+  constructor(asset: Asset): MutableAssetSymbols {
     super(asset);
     let existing = valueToMutableSymbols.get(asset);
     if (existing != null) {
@@ -142,6 +144,7 @@ export class MutableAssetSymbols extends MutableSymbols
     }
 
     this.#asset = asset;
+    return this;
   }
 
   clear() {
diff --git a/packages/core/core/src/public/Target.js b/packages/core/core/src/public/Target.js
index 534987049..7c9646281 100644
--- a/packages/core/core/src/public/Target.js
+++ b/packages/core/core/src/public/Target.js
@@ -4,6 +4,7 @@ import type {
   Target as ITarget,
   TargetSourceMapOptions,
   Environment as IEnvironment,
+  SourceLocation,
 } from '@parcel/types';
 import type {Target as TargetValue} from '../types';
 import Environment from './Environment';
@@ -16,9 +17,9 @@ export function targetToInternalTarget(target: ITarget): TargetValue {
 }
 
 export default class Target implements ITarget {
-  #target; // TargetValue
+  #target /*: TargetValue */;
 
-  constructor(target: TargetValue) {
+  constructor(target: TargetValue): Target {
     let existing = internalTargetToTarget.get(target);
     if (existing != null) {
       return existing;
@@ -27,6 +28,7 @@ export default class Target implements ITarget {
     this.#target = target;
     _targetToInternalTarget.set(this, target);
     internalTargetToTarget.set(target, this);
+    return this;
   }
 
   get distEntry(): ?FilePath {
@@ -53,7 +55,7 @@ export default class Target implements ITarget {
     return this.#target.publicUrl;
   }
 
-  get loc() {
+  get loc(): ?SourceLocation {
     return this.#target.loc;
   }
 }
diff --git a/packages/core/core/src/requests/AssetRequest.js b/packages/core/core/src/requests/AssetRequest.js
index 37ac0888a..905da021e 100644
--- a/packages/core/core/src/requests/AssetRequest.js
+++ b/packages/core/core/src/requests/AssetRequest.js
@@ -1,4 +1,6 @@
 // @flow strict-local
+
+import type {Async} from '@parcel/types';
 import type {StaticRunOpts} from '../RequestTracker';
 import type {AssetRequestInput, AssetRequestResult} from '../types';
 import type {ConfigAndCachePath} from './ParcelConfigRequest';
@@ -15,7 +17,7 @@ type RunInput = {|
 export type AssetRequest = {|
   id: string,
   +type: 'asset_request',
-  run: RunInput => Promise<AssetRequestResult>,
+  run: RunInput => Async<AssetRequestResult>,
   input: AssetRequestInput,
 |};
 
@@ -23,7 +25,9 @@ function generateRequestId(type, obj) {
   return `${type}:${md5FromObject(obj)}`;
 }
 
-export default function createAssetRequest(input: AssetRequestInput) {
+export default function createAssetRequest(
+  input: AssetRequestInput,
+): AssetRequest {
   return {
     type: 'asset_request',
     id: getId(input),
diff --git a/packages/core/core/src/requests/EntryRequest.js b/packages/core/core/src/requests/EntryRequest.js
index c357507c3..56c8d82cc 100644
--- a/packages/core/core/src/requests/EntryRequest.js
+++ b/packages/core/core/src/requests/EntryRequest.js
@@ -1,5 +1,6 @@
 // @flow strict-local
-import type {FilePath, File} from '@parcel/types';
+
+import type {Async, FilePath, File} from '@parcel/types';
 import type {StaticRunOpts} from '../RequestTracker';
 import type {Entry, ParcelOptions} from '../types';
 
@@ -14,7 +15,7 @@ type RunOpts = {|
 export type EntryRequest = {|
   id: string,
   +type: 'entry_request',
-  run: RunOpts => Promise<EntryResult>,
+  run: RunOpts => Async<EntryResult>,
   input: FilePath,
 |};
 
@@ -25,7 +26,7 @@ export type EntryResult = {|
 
 const type = 'entry_request';
 
-export default function createEntryRequest(input: FilePath) {
+export default function createEntryRequest(input: FilePath): EntryRequest {
   return {
     id: `${type}:${input}`,
     type,
diff --git a/packages/core/core/src/requests/ParcelConfigRequest.js b/packages/core/core/src/requests/ParcelConfigRequest.js
index f38387443..afefee23c 100644
--- a/packages/core/core/src/requests/ParcelConfigRequest.js
+++ b/packages/core/core/src/requests/ParcelConfigRequest.js
@@ -1,9 +1,10 @@
 // @flow strict-local
 import type {
+  Async,
   FilePath,
+  PackageName,
   RawParcelConfig,
   ResolvedParcelConfigFile,
-  PackageName,
 } from '@parcel/types';
 import type {StaticRunOpts} from '../RequestTracker';
 import type {
@@ -46,12 +47,17 @@ export type ParcelConfigRequest = {|
   id: string,
   type: string,
   input: null,
-  run: () => Promise<ConfigAndCachePath>,
+  run: RunOpts => Async<ConfigAndCachePath>,
+|};
+
+type ParcelConfigChain = {|
+  config: ParcelConfig,
+  extendedFiles: Array<FilePath>,
 |};
 
 const type = 'parcel_config_request';
 
-export default function createParcelConfigRequest() {
+export default function createParcelConfigRequest(): ParcelConfigRequest {
   return {
     id: type,
     type,
@@ -82,7 +88,9 @@ export default function createParcelConfigRequest() {
   };
 }
 
-export async function loadParcelConfig(options: ParcelOptions) {
+export async function loadParcelConfig(
+  options: ParcelOptions,
+): Promise<ParcelConfigChain> {
   // Resolve plugins from cwd when a config is passed programmatically
   let parcelConfig = options.config
     ? await create(
@@ -110,7 +118,9 @@ export async function loadParcelConfig(options: ParcelOptions) {
   return parcelConfig;
 }
 
-export async function resolveParcelConfig(options: ParcelOptions) {
+export async function resolveParcelConfig(
+  options: ParcelOptions,
+): Promise<?ParcelConfigChain> {
   let filePath = getResolveFrom(options);
   let configPath = await resolveConfig(options.inputFS, filePath, [
     '.parcelrc',
@@ -125,14 +135,14 @@ export async function resolveParcelConfig(options: ParcelOptions) {
 export function create(
   config: ResolvedParcelConfigFile,
   options: ParcelOptions,
-) {
+): Promise<ParcelConfigChain> {
   return processConfigChain(config, config.filePath, options);
 }
 
 export async function readAndProcessConfigChain(
   configPath: FilePath,
   options: ParcelOptions,
-) {
+): Promise<ParcelConfigChain> {
   let contents = await options.inputFS.readFile(configPath, 'utf8');
   let config: RawParcelConfig;
   try {
@@ -235,7 +245,7 @@ export async function processConfigChain(
   configFile: RawParcelConfig | ResolvedParcelConfigFile,
   filePath: FilePath,
   options: ParcelOptions,
-) {
+): Promise<ParcelConfigChain> {
   // Validate config...
   let relativePath = path.relative(options.inputFS.cwd(), filePath);
   validateConfigFile(configFile, relativePath);
@@ -275,7 +285,7 @@ export async function resolveExtends(
   ext: string,
   configPath: FilePath,
   options: ParcelOptions,
-) {
+): Promise<FilePath> {
   if (ext.startsWith('.')) {
     return path.resolve(path.dirname(configPath), ext);
   } else {
diff --git a/packages/core/core/src/requests/PathRequest.js b/packages/core/core/src/requests/PathRequest.js
index 65b33fe28..1b2ee854f 100644
--- a/packages/core/core/src/requests/PathRequest.js
+++ b/packages/core/core/src/requests/PathRequest.js
@@ -33,7 +33,14 @@ type RunOpts = {|
 
 const type = 'path_request';
 
-export default function createPathRequest(input: Dependency) {
+export default function createPathRequest(
+  input: Dependency,
+): {|
+  id: string,
+  input: Dependency,
+  run: ({|input: Dependency, ...StaticRunOpts|}) => Async<?AssetGroup>,
+  +type: string,
+|} {
   return {
     id: input.id,
     type,
diff --git a/packages/core/core/src/requests/TargetRequest.js b/packages/core/core/src/requests/TargetRequest.js
index b0b0fb50f..fac3d80be 100644
--- a/packages/core/core/src/requests/TargetRequest.js
+++ b/packages/core/core/src/requests/TargetRequest.js
@@ -1,7 +1,9 @@
 // @flow strict-local
+
 import type {Diagnostic} from '@parcel/diagnostic';
 import type {FileSystem} from '@parcel/fs';
 import type {
+  Async,
   Engines,
   File,
   FilePath,
@@ -66,13 +68,13 @@ const COMMON_TARGETS = ['main', 'module', 'browser', 'types'];
 export type TargetRequest = {|
   id: string,
   +type: 'target_request',
-  run: RunOpts => Promise<TargetResolveResult>,
+  run: RunOpts => Async<TargetResolveResult>,
   input: Entry,
 |};
 
 const type = 'target_request';
 
-export default function createTargetRequest(input: Entry) {
+export default function createTargetRequest(input: Entry): TargetRequest {
   return {
     id: `${type}:${md5FromObject(input)}`,
     type,
@@ -256,7 +258,9 @@ export class TargetResolver {
     return {targets, files};
   }
 
-  async resolvePackageTargets(rootDir: FilePath) {
+  async resolvePackageTargets(
+    rootDir: FilePath,
+  ): Promise<{|files: Array<File>, targets: Map<string, Target>|}> {
     let conf = await loadConfig(this.fs, path.join(rootDir, 'index'), [
       'package.json',
     ]);
diff --git a/packages/core/core/src/serializer.js b/packages/core/core/src/serializer.js
index 994abf6e5..c24735363 100644
--- a/packages/core/core/src/serializer.js
+++ b/packages/core/core/src/serializer.js
@@ -144,7 +144,7 @@ function mapObject(object: any, fn: (val: any) => any, preOrder = false): any {
   return mapped;
 }
 
-export function prepareForSerialization(object: any) {
+export function prepareForSerialization(object: any): any {
   return mapObject(
     object,
     value => {
@@ -181,7 +181,7 @@ export function prepareForSerialization(object: any) {
   );
 }
 
-export function restoreDeserializedObject(object: any) {
+export function restoreDeserializedObject(object: any): any {
   return mapObject(object, value => {
     // If the value has a $$type property, use it to restore the object type
     if (value && value.$$type) {
diff --git a/packages/core/core/src/types.js b/packages/core/core/src/types.js
index 999bf6205..702b22d8a 100644
--- a/packages/core/core/src/types.js
+++ b/packages/core/core/src/types.js
@@ -29,7 +29,7 @@ import type {
   TargetDescriptor,
   HMROptions,
 } from '@parcel/types';
-
+import type {SharedReference} from '@parcel/workers';
 import type {FileSystem} from '@parcel/fs';
 import type Cache from '@parcel/cache';
 import type {PackageManager} from '@parcel/package-manager';
@@ -207,13 +207,16 @@ export type AssetRequestInput = {|
   sideEffects?: boolean,
   code?: string,
   pipeline?: ?string,
-  optionsRef: number,
+  optionsRef: SharedReference,
   isURL?: boolean,
 |};
 
 export type AssetRequestResult = Array<Asset>;
 // Asset group nodes are essentially used as placeholders for the results of an asset request
-export type AssetGroup = $Rest<AssetRequestInput, {|optionsRef: number|}>;
+export type AssetGroup = $Rest<
+  AssetRequestInput,
+  {|optionsRef: SharedReference|},
+>;
 export type AssetGroupNode = {|
   id: string,
   +type: 'asset_group',
@@ -374,13 +377,13 @@ export type BundleGroupNode = {|
 
 export type TransformationOpts = {|
   request: AssetGroup,
-  optionsRef: number,
+  optionsRef: SharedReference,
   configCachePath: string,
 |};
 
 export type ValidationOpts = {|
   requests: AssetGroup[],
-  optionsRef: number,
+  optionsRef: SharedReference,
   configCachePath: string,
 |};
 
diff --git a/packages/core/core/src/utils.js b/packages/core/core/src/utils.js
index 4bed67c4c..dc1df5402 100644
--- a/packages/core/core/src/utils.js
+++ b/packages/core/core/src/utils.js
@@ -30,7 +30,7 @@ export function assertSignalNotAborted(signal: ?AbortSignal): void {
 }
 
 export class BuildAbortError extends Error {
-  name = 'BuildAbortError';
+  name: string = 'BuildAbortError';
 }
 
 let coreRegistered;
diff --git a/packages/core/core/src/worker.js b/packages/core/core/src/worker.js
index 6375c3a15..c1d1eae35 100644
--- a/packages/core/core/src/worker.js
+++ b/packages/core/core/src/worker.js
@@ -1,13 +1,17 @@
 // @flow strict-local
+
 import type {Bundle, ParcelOptions, ProcessedParcelConfig} from './types';
-import type {WorkerApi} from '@parcel/workers';
+import type {SharedReference, WorkerApi} from '@parcel/workers';
 
 import invariant from 'assert';
 import nullthrows from 'nullthrows';
 import BundleGraph from './BundleGraph';
-import Transformation, {type TransformationOpts} from './Transformation';
+import Transformation, {
+  type TransformationOpts,
+  type TransformationResult,
+} from './Transformation';
 import {reportWorker} from './ReporterRunner';
-import PackagerRunner from './PackagerRunner';
+import PackagerRunner, {type BundleInfo} from './PackagerRunner';
 import Validation, {type ValidationOpts} from './Validation';
 import ParcelConfig from './ParcelConfig';
 import {registerCoreWithSerializer} from './utils';
@@ -22,12 +26,12 @@ registerCoreWithSerializer();
 // https://github.com/facebook/flow/issues/2835
 type WorkerTransformationOpts = {|
   ...$Diff<TransformationOpts, {|workerApi: mixed, options: ParcelOptions|}>,
-  optionsRef: number,
+  optionsRef: SharedReference,
   configCachePath: string,
 |};
 type WorkerValidationOpts = {|
   ...$Diff<ValidationOpts, {|workerApi: mixed, options: ParcelOptions|}>,
-  optionsRef: number,
+  optionsRef: SharedReference,
   configCachePath: string,
 |};
 
@@ -60,7 +64,7 @@ async function loadConfig(cachePath, options) {
 export async function runTransform(
   workerApi: WorkerApi,
   opts: WorkerTransformationOpts,
-) {
+): Promise<TransformationResult> {
   let {optionsRef, configCachePath, ...rest} = opts;
   let options = loadOptions(optionsRef, workerApi);
   let config = await loadConfig(configCachePath, options);
@@ -77,7 +81,7 @@ export async function runTransform(
 export async function runValidate(
   workerApi: WorkerApi,
   opts: WorkerValidationOpts,
-) {
+): Promise<void> {
   let {optionsRef, configCachePath, ...rest} = opts;
   let options = loadOptions(optionsRef, workerApi);
   let config = await loadConfig(configCachePath, options);
@@ -101,16 +105,16 @@ export function runPackage(
     optionsRef,
   }: {|
     bundle: Bundle,
-    bundleGraphReference: number,
-    configRef: number,
+    bundleGraphReference: SharedReference,
+    configRef: SharedReference,
     cacheKeys: {|
       content: string,
       map: string,
       info: string,
     |},
-    optionsRef: number,
+    optionsRef: SharedReference,
   |},
-) {
+): Promise<BundleInfo> {
   let bundleGraph = workerApi.getSharedReference(bundleGraphReference);
   invariant(bundleGraph instanceof BundleGraph);
   let options = loadOptions(optionsRef, workerApi);
diff --git a/packages/core/diagnostic/src/diagnostic.js b/packages/core/diagnostic/src/diagnostic.js
index e6e21620f..5eafa9735 100644
--- a/packages/core/diagnostic/src/diagnostic.js
+++ b/packages/core/diagnostic/src/diagnostic.js
@@ -179,7 +179,13 @@ export function generateJSONCodeHighlights(
   });
 }
 
-export function getJSONSourceLocation(pos: any, type?: ?'key' | 'value') {
+export function getJSONSourceLocation(
+  pos: any,
+  type?: ?'key' | 'value',
+): {|
+  start: DiagnosticHighlightLocation,
+  end: DiagnosticHighlightLocation,
+|} {
   if (!type && pos.value) {
     // key and value
     return {
diff --git a/packages/core/fs/src/MemoryFS.js b/packages/core/fs/src/MemoryFS.js
index 55236bd14..419b66399 100644
--- a/packages/core/fs/src/MemoryFS.js
+++ b/packages/core/fs/src/MemoryFS.js
@@ -75,14 +75,15 @@ export class MemoryFS implements FileSystem {
     });
   }
 
-  static deserialize(opts: SerializedMemoryFS) {
-    if (instances.has(opts.id)) {
+  static deserialize(opts: SerializedMemoryFS): MemoryFS | WorkerFS {
+    let existing = instances.get(opts.id);
+    if (existing != null) {
       // Correct the count of worker instances since serialization assumes a new instance is created
       WorkerFarm.getWorkerApi().runHandle(opts.handle, [
         'decrementWorkerInstance',
         [],
       ]);
-      return instances.get(opts.id);
+      return existing;
     }
 
     let fs = new WorkerFS(opts.id, nullthrows(opts.handle));
@@ -122,7 +123,7 @@ export class MemoryFS implements FileSystem {
     }
   }
 
-  cwd() {
+  cwd(): FilePath {
     return this._cwd;
   }
 
@@ -217,7 +218,7 @@ export class MemoryFS implements FileSystem {
     await this.writeFile(destination, contents);
   }
 
-  statSync(filePath: FilePath) {
+  statSync(filePath: FilePath): Stat {
     filePath = this._normalizePath(filePath);
 
     let dir = this.dirs.get(filePath);
@@ -234,7 +235,7 @@ export class MemoryFS implements FileSystem {
   }
 
   // eslint-disable-next-line require-await
-  async stat(filePath: FilePath) {
+  async stat(filePath: FilePath): Promise<Stat> {
     return this.statSync(filePath);
   }
 
@@ -283,7 +284,7 @@ export class MemoryFS implements FileSystem {
     return this.readdirSync(dir, opts);
   }
 
-  async unlink(filePath: FilePath) {
+  async unlink(filePath: FilePath): Promise<void> {
     filePath = this._normalizePath(filePath);
     if (!this.files.has(filePath) && !this.dirs.has(filePath)) {
       throw new FSError('ENOENT', filePath, 'does not exist');
@@ -306,7 +307,7 @@ export class MemoryFS implements FileSystem {
     return Promise.resolve();
   }
 
-  async mkdirp(dir: FilePath) {
+  async mkdirp(dir: FilePath): Promise<void> {
     dir = this._normalizePath(dir);
     if (this.dirs.has(dir)) {
       return Promise.resolve();
@@ -339,7 +340,7 @@ export class MemoryFS implements FileSystem {
     return Promise.resolve();
   }
 
-  async rimraf(filePath: FilePath) {
+  async rimraf(filePath: FilePath): Promise<void> {
     filePath = this._normalizePath(filePath);
 
     if (this.dirs.has(filePath)) {
@@ -468,20 +469,20 @@ export class MemoryFS implements FileSystem {
     }
   }
 
-  createReadStream(filePath: FilePath) {
+  createReadStream(filePath: FilePath): ReadStream {
     return new ReadStream(this, filePath);
   }
 
-  createWriteStream(filePath: FilePath, options: ?FileOptions) {
+  createWriteStream(filePath: FilePath, options: ?FileOptions): WriteStream {
     return new WriteStream(this, filePath, options);
   }
 
-  realpathSync(filePath: FilePath) {
+  realpathSync(filePath: FilePath): FilePath {
     return this._normalizePath(filePath);
   }
 
   // eslint-disable-next-line require-await
-  async realpath(filePath: FilePath) {
+  async realpath(filePath: FilePath): Promise<FilePath> {
     return this.realpathSync(filePath);
   }
 
@@ -496,13 +497,13 @@ export class MemoryFS implements FileSystem {
     });
   }
 
-  existsSync(filePath: FilePath) {
+  existsSync(filePath: FilePath): boolean {
     filePath = this._normalizePath(filePath);
     return this.files.has(filePath) || this.dirs.has(filePath);
   }
 
   // eslint-disable-next-line require-await
-  async exists(filePath: FilePath) {
+  async exists(filePath: FilePath): Promise<boolean> {
     return this.existsSync(filePath);
   }
 
@@ -737,26 +738,26 @@ class Entry {
     this.mode = mode;
   }
 
-  getSize() {
+  getSize(): number {
     return 0;
   }
 
-  stat() {
+  stat(): Stat {
     return new Stat(this);
   }
 }
 
 class Stat {
-  dev = 0;
-  ino = 0;
+  dev: number = 0;
+  ino: number = 0;
   mode: number;
-  nlink = 0;
-  uid = 0;
-  gid = 0;
-  rdev = 0;
+  nlink: number = 0;
+  uid: number = 0;
+  gid: number = 0;
+  rdev: number = 0;
   size: number;
-  blksize = 0;
-  blocks = 0;
+  blksize: number = 0;
+  blocks: number = 0;
   atimeMs: number;
   mtimeMs: number;
   ctimeMs: number;
@@ -779,31 +780,31 @@ class Stat {
     this.birthtime = new Date(entry.birthtime);
   }
 
-  isFile() {
+  isFile(): boolean {
     return Boolean(this.mode & S_IFREG);
   }
 
-  isDirectory() {
+  isDirectory(): boolean {
     return Boolean(this.mode & S_IFDIR);
   }
 
-  isBlockDevice() {
+  isBlockDevice(): boolean {
     return false;
   }
 
-  isCharacterDevice() {
+  isCharacterDevice(): boolean {
     return false;
   }
 
-  isSymbolicLink() {
+  isSymbolicLink(): boolean {
     return false;
   }
 
-  isFIFO() {
+  isFIFO(): boolean {
     return false;
   }
 
-  isSocket() {
+  isSocket(): boolean {
     return false;
   }
 }
@@ -817,31 +818,31 @@ class Dirent {
     this.#mode = entry.mode;
   }
 
-  isFile() {
+  isFile(): boolean {
     return Boolean(this.#mode & S_IFREG);
   }
 
-  isDirectory() {
+  isDirectory(): boolean {
     return Boolean(this.#mode & S_IFDIR);
   }
 
-  isBlockDevice() {
+  isBlockDevice(): boolean {
     return false;
   }
 
-  isCharacterDevice() {
+  isCharacterDevice(): boolean {
     return false;
   }
 
-  isSymbolicLink() {
+  isSymbolicLink(): boolean {
     return false;
   }
 
-  isFIFO() {
+  isFIFO(): boolean {
     return false;
   }
 
-  isSocket() {
+  isSocket(): boolean {
     return false;
   }
 }
@@ -863,7 +864,7 @@ class File extends Entry {
     this.buffer = buffer;
   }
 
-  getSize() {
+  getSize(): number {
     return this.buffer.byteLength;
   }
 }
@@ -928,8 +929,8 @@ class WorkerFS extends MemoryFS {
     ]);
   }
 
-  static deserialize(opts: SerializedMemoryFS) {
-    return instances.get(opts.id);
+  static deserialize(opts: SerializedMemoryFS): MemoryFS {
+    return nullthrows(instances.get(opts.id));
   }
 
   serialize(): SerializedMemoryFS {
@@ -943,33 +944,33 @@ class WorkerFS extends MemoryFS {
     filePath: FilePath,
     contents: Buffer | string,
     options: ?FileOptions,
-  ) {
+  ): Promise<void> {
     super.writeFile(filePath, contents, options);
     let buffer = makeShared(contents);
     return this.handleFn('writeFile', [filePath, buffer, options]);
   }
 
-  unlink(filePath: FilePath) {
+  unlink(filePath: FilePath): Promise<void> {
     super.unlink(filePath);
     return this.handleFn('unlink', [filePath]);
   }
 
-  mkdirp(dir: FilePath) {
+  mkdirp(dir: FilePath): Promise<void> {
     super.mkdirp(dir);
     return this.handleFn('mkdirp', [dir]);
   }
 
-  rimraf(filePath: FilePath) {
+  rimraf(filePath: FilePath): Promise<void> {
     super.rimraf(filePath);
     return this.handleFn('rimraf', [filePath]);
   }
 
-  ncp(source: FilePath, destination: FilePath) {
+  ncp(source: FilePath, destination: FilePath): Promise<void> {
     super.ncp(source, destination);
     return this.handleFn('ncp', [source, destination]);
   }
 
-  symlink(target: FilePath, path: FilePath) {
+  symlink(target: FilePath, path: FilePath): Promise<void> {
     super.symlink(target, path);
     return this.handleFn('symlink', [target, path]);
   }
diff --git a/packages/core/fs/src/NodeFS.js b/packages/core/fs/src/NodeFS.js
index b50b21d70..7879675df 100644
--- a/packages/core/fs/src/NodeFS.js
+++ b/packages/core/fs/src/NodeFS.js
@@ -1,4 +1,5 @@
 // @flow
+import type {ReadStream, Stats} from 'fs';
 import type {Writable} from 'stream';
 import type {FileOptions, FileSystem} from './types';
 import type {FilePath} from '@parcel/types';
@@ -24,23 +25,24 @@ import packageJSON from '../package.json';
 const realpath = promisify(fs.realpath);
 
 export class NodeFS implements FileSystem {
-  readFile = promisify(fs.readFile);
-  copyFile = promisify(fs.copyFile);
-  stat = promisify(fs.stat);
-  readdir = promisify(fs.readdir);
-  unlink = promisify(fs.unlink);
-  utimes = promisify(fs.utimes);
-  mkdirp = promisify(mkdirp);
-  rimraf = promisify(rimraf);
-  ncp = promisify(ncp);
-  createReadStream = fs.createReadStream;
-  cwd = process.cwd;
-  chdir = process.chdir;
-
-  statSync = fs.statSync;
-  realpathSync = fs.realpathSync;
-  existsSync = fs.existsSync;
-  readdirSync = (fs.readdirSync: any);
+  readFile: any = promisify(fs.readFile);
+  copyFile: any = promisify(fs.copyFile);
+  stat: any = promisify(fs.stat);
+  readdir: any = promisify(fs.readdir);
+  unlink: any = promisify(fs.unlink);
+  utimes: any = promisify(fs.utimes);
+  mkdirp: any = promisify(mkdirp);
+  rimraf: any = promisify(rimraf);
+  ncp: any = promisify(ncp);
+  createReadStream: (path: string, options?: any) => ReadStream =
+    fs.createReadStream;
+  cwd: () => string = process.cwd;
+  chdir: (directory: string) => void = process.chdir;
+
+  statSync: (path: string) => Stats = fs.statSync;
+  realpathSync: (path: string, cache?: any) => string = fs.realpathSync;
+  existsSync: (path: string) => boolean = fs.existsSync;
+  readdirSync: any = (fs.readdirSync: any);
 
   createWriteStream(filePath: string, options: any): Writable {
     return fsWriteStreamAtomic(filePath, options);
@@ -108,11 +110,11 @@ export class NodeFS implements FileSystem {
     await watcher.writeSnapshot(dir, snapshot, opts);
   }
 
-  static deserialize() {
+  static deserialize(): NodeFS {
     return new NodeFS();
   }
 
-  serialize() {
+  serialize(): null {
     return null;
   }
 }
diff --git a/packages/core/fs/src/OverlayFS.js b/packages/core/fs/src/OverlayFS.js
index 16cc16286..53f9551d7 100644
--- a/packages/core/fs/src/OverlayFS.js
+++ b/packages/core/fs/src/OverlayFS.js
@@ -1,4 +1,6 @@
 // @flow
+
+import type {Stats} from 'fs';
 import type {FileSystem, ReaddirOptions} from './types';
 import type {FilePath} from '@parcel/types';
 import type {
@@ -54,11 +56,11 @@ export class OverlayFS implements FileSystem {
     this.readable = readable;
   }
 
-  static deserialize(opts: any) {
+  static deserialize(opts: any): OverlayFS {
     return new OverlayFS(opts.writable, opts.readable);
   }
 
-  serialize() {
+  serialize(): {|$$raw: boolean, readable: FileSystem, writable: FileSystem|} {
     return {
       $$raw: false,
       writable: this.writable,
@@ -66,8 +68,10 @@ export class OverlayFS implements FileSystem {
     };
   }
 
-  readFile = read('readFile');
-  writeFile = write('writeFile');
+  readFile: (
+    ...args: Array<any>
+  ) => Promise<Buffer & string & $Shape<Stats>> = read('readFile');
+  writeFile: (...args: Array<any>) => any = write('writeFile');
   async copyFile(source: FilePath, destination: FilePath) {
     if (await this.writable.exists(source)) {
       await this.writable.writeFile(
@@ -81,21 +85,30 @@ export class OverlayFS implements FileSystem {
       );
     }
   }
-  stat = read('stat');
-  unlink = write('unlink');
-  mkdirp = write('mkdirp');
-  rimraf = write('rimraf');
-  ncp = write('ncp');
-  createReadStream = checkExists('createReadStream');
-  createWriteStream = write('createWriteStream');
-  cwd = readSync('cwd');
-  chdir = readSync('chdir');
-  realpath = checkExists('realpath');
-
-  readFileSync = readSync('readFileSync');
-  statSync = readSync('statSync');
-  existsSync = readSync('existsSync');
-  realpathSync = checkExists('realpathSync');
+  stat: (
+    ...args: Array<any>
+  ) => Promise<Buffer & string & $Shape<Stats>> = read('stat');
+  unlink: (...args: Array<any>) => any = write('unlink');
+  mkdirp: (...args: Array<any>) => any = write('mkdirp');
+  rimraf: (...args: Array<any>) => any = write('rimraf');
+  ncp: (...args: Array<any>) => any = write('ncp');
+  createReadStream: (
+    filePath: FilePath,
+    ...args: Array<any>
+  ) => any = checkExists('createReadStream');
+  createWriteStream: (...args: Array<any>) => any = write('createWriteStream');
+  cwd: (...args: Array<any>) => any = readSync('cwd');
+  chdir: (...args: Array<any>) => any = readSync('chdir');
+  realpath: (filePath: FilePath, ...args: Array<any>) => any = checkExists(
+    'realpath',
+  );
+
+  readFileSync: (...args: Array<any>) => any = readSync('readFileSync');
+  statSync: (...args: Array<any>) => any = readSync('statSync');
+  existsSync: (...args: Array<any>) => any = readSync('existsSync');
+  realpathSync: (filePath: FilePath, ...args: Array<any>) => any = checkExists(
+    'realpathSync',
+  );
 
   async exists(filePath: FilePath): Promise<boolean> {
     return (
diff --git a/packages/core/fs/src/types.js b/packages/core/fs/src/types.js
index 4a5259c81..5b72e965b 100644
--- a/packages/core/fs/src/types.js
+++ b/packages/core/fs/src/types.js
@@ -15,9 +15,9 @@ export type ReaddirOptions =
 
 export interface FileSystem {
   readFile(filePath: FilePath): Promise<Buffer>;
-  readFile(filePath: FilePath, encoding?: buffer$Encoding): Promise<string>;
+  readFile(filePath: FilePath, encoding: buffer$Encoding): Promise<string>;
   readFileSync(filePath: FilePath): Buffer;
-  readFileSync(filePath: FilePath, encoding?: buffer$Encoding): string;
+  readFileSync(filePath: FilePath, encoding: buffer$Encoding): string;
   writeFile(
     filePath: FilePath,
     contents: Buffer | string,
diff --git a/packages/core/logger/src/Logger.js b/packages/core/logger/src/Logger.js
index d7256e575..87952c885 100644
--- a/packages/core/logger/src/Logger.js
+++ b/packages/core/logger/src/Logger.js
@@ -12,7 +12,7 @@ import {inspect} from 'util';
 import {errorToDiagnostic, anyToDiagnostic} from '@parcel/diagnostic';
 
 class Logger {
-  #logEmitter = new ValueEmitter<LogEvent>();
+  #logEmitter /*: ValueEmitter<LogEvent> */ = new ValueEmitter();
 
   onLog(cb: (event: LogEvent) => mixed): IDisposable {
     return this.#logEmitter.addListener(cb);
@@ -75,7 +75,7 @@ class Logger {
   }
 }
 
-const logger = new Logger();
+const logger: Logger = new Logger();
 export default logger;
 
 export type PluginLoggerOpts = {|
diff --git a/packages/core/package-manager/src/MockPackageInstaller.js b/packages/core/package-manager/src/MockPackageInstaller.js
index 733973f4b..50dd6e889 100644
--- a/packages/core/package-manager/src/MockPackageInstaller.js
+++ b/packages/core/package-manager/src/MockPackageInstaller.js
@@ -18,7 +18,7 @@ type Package = {|
 // This PackageInstaller implementation simply copies files from one filesystem to another.
 // Mostly useful for testing purposes.
 export class MockPackageInstaller implements PackageInstaller {
-  packages = new Map<string, Package>();
+  packages: Map<string, Package> = new Map<string, Package>();
 
   register(packageName: string, fs: FileSystem, packagePath: FilePath) {
     this.packages.set(packageName, {fs, packagePath});
@@ -55,7 +55,7 @@ export class MockPackageInstaller implements PackageInstaller {
     moduleRequest: ModuleRequest,
     fs: FileSystem,
     packagePath: FilePath,
-  ) {
+  ): Promise<any> {
     let pkg = this.packages.get(moduleRequest.name);
     if (!pkg) {
       throw new Error('Unknown package ' + moduleRequest.name);
diff --git a/packages/core/package-manager/src/NodePackageManager.js b/packages/core/package-manager/src/NodePackageManager.js
index 580443758..341a2be48 100644
--- a/packages/core/package-manager/src/NodePackageManager.js
+++ b/packages/core/package-manager/src/NodePackageManager.js
@@ -40,11 +40,15 @@ export class NodePackageManager implements PackageManager {
     this.installer = installer;
   }
 
-  static deserialize(opts: any) {
+  static deserialize(opts: any): NodePackageManager {
     return new NodePackageManager(opts.fs, opts.installer);
   }
 
-  serialize() {
+  serialize(): {|
+    $$raw: boolean,
+    fs: FileSystem,
+    installer: ?PackageInstaller,
+  |} {
     return {
       $$raw: false,
       fs: this.fs,
@@ -56,17 +60,17 @@ export class NodePackageManager implements PackageManager {
     name: ModuleSpecifier,
     from: FilePath,
     opts: ?{|range?: SemverRange, autoinstall?: boolean, saveDev?: boolean|},
-  ) {
+  ): Promise<any> {
     let {resolved} = await this.resolve(name, from, opts);
     return this.load(resolved, from);
   }
 
-  requireSync(name: ModuleSpecifier, from: FilePath) {
+  requireSync(name: ModuleSpecifier, from: FilePath): any {
     let {resolved} = this.resolveSync(name, from);
     return this.load(resolved, from);
   }
 
-  load(resolved: FilePath, from: FilePath) {
+  load(resolved: FilePath, from: FilePath): any {
     if (!path.isAbsolute(resolved)) {
       // Node builtin module
       // $FlowFixMe
@@ -110,7 +114,7 @@ export class NodePackageManager implements PackageManager {
     name: ModuleSpecifier,
     from: FilePath,
     options?: ?{|range?: string, autoinstall?: boolean, saveDev?: boolean|},
-  ) {
+  ): Promise<ResolveResult> {
     let basedir = path.dirname(from);
     let key = basedir + ':' + name;
     let resolved = this.cache.get(key);
@@ -220,7 +224,7 @@ export class NodePackageManager implements PackageManager {
     return resolved;
   }
 
-  resolveSync(name: ModuleSpecifier, from: FilePath) {
+  resolveSync(name: ModuleSpecifier, from: FilePath): ResolveResult {
     let basedir = path.dirname(from);
     return resolveSync(this.fs, name, {
       basedir,
diff --git a/packages/core/plugin/src/PluginAPI.js b/packages/core/plugin/src/PluginAPI.js
index 39759e843..65d9eb9af 100644
--- a/packages/core/plugin/src/PluginAPI.js
+++ b/packages/core/plugin/src/PluginAPI.js
@@ -12,7 +12,7 @@ import type {
   Validator as ValidatorOpts,
 } from '@parcel/types';
 
-export const CONFIG = Symbol.for('parcel-plugin-config');
+export const CONFIG: symbol = Symbol.for('parcel-plugin-config');
 
 export class Transformer {
   constructor(opts: TransformerOpts) {
diff --git a/packages/core/register/src/register.js b/packages/core/register/src/register.js
index 8123a50e7..e856fd926 100644
--- a/packages/core/register/src/register.js
+++ b/packages/core/register/src/register.js
@@ -148,10 +148,10 @@ function register(inputOpts?: InitialParcelOptions): IDisposable {
   return disposable;
 }
 
-let disposable = register();
+let disposable: IDisposable = register();
 register.dispose = disposable.dispose;
 
 // Support both commonjs and ES6 modules
-exports = module.exports = register;
+module.exports = register;
 exports.default = register;
 exports.__esModule = true;
diff --git a/packages/core/utils/src/bundle-url.js b/packages/core/utils/src/bundle-url.js
index 3ed766fc5..30f77d2b1 100644
--- a/packages/core/utils/src/bundle-url.js
+++ b/packages/core/utils/src/bundle-url.js
@@ -1,7 +1,7 @@
 // @flow strict-local
 
 let bundleURL: ?string = null;
-function getBundleURLCached() {
+function getBundleURLCached(): string {
   if (bundleURL == null) {
     bundleURL = _getBundleURL();
   }
diff --git a/packages/core/utils/src/dependency-location.js b/packages/core/utils/src/dependency-location.js
index 4a8c2cd74..74ce22c2a 100644
--- a/packages/core/utils/src/dependency-location.js
+++ b/packages/core/utils/src/dependency-location.js
@@ -9,7 +9,11 @@ export default function createDependencyLocation(
   columnOffset: number = 0,
   // Imports are usually wrapped in quotes
   importWrapperLength: number = 2,
-) {
+): {|
+  end: {|column: number, line: number|},
+  filePath: string,
+  start: {|column: number, line: number|},
+|} {
   return {
     filePath: moduleSpecifier,
     start: {
diff --git a/packages/core/utils/src/generateCertificate.js b/packages/core/utils/src/generateCertificate.js
index 5a910df62..e972ea251 100644
--- a/packages/core/utils/src/generateCertificate.js
+++ b/packages/core/utils/src/generateCertificate.js
@@ -8,7 +8,7 @@ export default async function generateCertificate(
   fs: FileSystem,
   cacheDir: string,
   host: ?string,
-) {
+): Promise<{|cert: Buffer, key: Buffer|}> {
   let certDirectory = cacheDir;
 
   const privateKeyPath = path.join(certDirectory, 'private.pem');
diff --git a/packages/core/utils/src/getCertificate.js b/packages/core/utils/src/getCertificate.js
index 1140608a5..2eb94b5be 100644
--- a/packages/core/utils/src/getCertificate.js
+++ b/packages/core/utils/src/getCertificate.js
@@ -5,7 +5,7 @@ import type {FileSystem} from '@parcel/fs';
 export default async function getCertificate(
   fs: FileSystem,
   options: HTTPSOptions,
-) {
+): Promise<{|cert: Buffer, key: Buffer|}> {
   try {
     let cert = await fs.readFile(options.cert);
     let key = await fs.readFile(options.key);
diff --git a/packages/core/utils/src/glob.js b/packages/core/utils/src/glob.js
index ab3bcb767..9711215db 100644
--- a/packages/core/utils/src/glob.js
+++ b/packages/core/utils/src/glob.js
@@ -8,11 +8,11 @@ import fastGlob, {type FastGlobOptions} from 'fast-glob';
 import {isMatch} from 'micromatch';
 import {normalizeSeparators} from './path';
 
-export function isGlob(p: FilePath) {
+export function isGlob(p: FilePath): any {
   return _isGlob(normalizeSeparators(p));
 }
 
-export function isGlobMatch(filePath: FilePath, glob: Glob) {
+export function isGlobMatch(filePath: FilePath, glob: Glob): any {
   return isMatch(filePath, normalizeSeparators(glob));
 }
 
diff --git a/packages/core/utils/src/isDirectoryInside.js b/packages/core/utils/src/isDirectoryInside.js
index d44317bd5..c69620464 100644
--- a/packages/core/utils/src/isDirectoryInside.js
+++ b/packages/core/utils/src/isDirectoryInside.js
@@ -2,7 +2,10 @@
 import type {FilePath} from '@parcel/types';
 import path from 'path';
 
-export default function isDirectoryInside(child: FilePath, parent: FilePath) {
+export default function isDirectoryInside(
+  child: FilePath,
+  parent: FilePath,
+): boolean {
   const relative = path.relative(parent, child);
   return !relative.startsWith('..') && !path.isAbsolute(relative);
 }
diff --git a/packages/core/utils/src/path.js b/packages/core/utils/src/path.js
index ab92c36dd..2464c1158 100644
--- a/packages/core/utils/src/path.js
+++ b/packages/core/utils/src/path.js
@@ -28,6 +28,6 @@ export function relativePath(
   from: string,
   to: string,
   leadingDotSlash: boolean = true,
-) {
+): FilePath {
   return normalizePath(path.relative(from, to), leadingDotSlash);
 }
diff --git a/packages/core/utils/src/relativeBundlePath.js b/packages/core/utils/src/relativeBundlePath.js
index 64b93cf77..c1f2a42a1 100644
--- a/packages/core/utils/src/relativeBundlePath.js
+++ b/packages/core/utils/src/relativeBundlePath.js
@@ -1,6 +1,6 @@
 // @flow strict-local
 
-import type {NamedBundle} from '@parcel/types';
+import type {FilePath, NamedBundle} from '@parcel/types';
 
 import path from 'path';
 import {relativePath} from './path';
@@ -9,7 +9,7 @@ export function relativeBundlePath(
   from: NamedBundle,
   to: NamedBundle,
   opts: {|leadingDotSlash: boolean|} = {leadingDotSlash: true},
-) {
+): FilePath {
   return relativePath(
     path.dirname(from.filePath),
     to.filePath,
diff --git a/packages/core/utils/src/serializeObject.js b/packages/core/utils/src/serializeObject.js
index 2e017ad68..a7d9cb93a 100644
--- a/packages/core/utils/src/serializeObject.js
+++ b/packages/core/utils/src/serializeObject.js
@@ -6,7 +6,7 @@ import serialize from 'serialize-to-js';
 export default function serializeObject(
   obj: mixed,
   shouldMinify: boolean = false,
-) {
+): ?string {
   let code = `module.exports = ${serialize(obj)};`;
 
   if (shouldMinify) {
diff --git a/packages/core/utils/src/sourcemap.js b/packages/core/utils/src/sourcemap.js
index 3bdea99f6..8ad67717a 100644
--- a/packages/core/utils/src/sourcemap.js
+++ b/packages/core/utils/src/sourcemap.js
@@ -7,7 +7,9 @@ import {normalizeSeparators} from './path';
 const SOURCEMAP_RE = /(?:\/\*|\/\/)\s*[@#]\s*sourceMappingURL\s*=\s*([^\s*]+)(?:\s*\*\/)?\s*$/;
 const DATA_URL_RE = /^data:[^;]+(?:;charset=[^;]+)?;base64,(.*)/;
 
-export function matchSourceMappingURL(contents: string) {
+export function matchSourceMappingURL(
+  contents: string,
+): null | RegExp$matchResult {
   return contents.match(SOURCEMAP_RE);
 }
 
@@ -15,7 +17,7 @@ export async function loadSourceMapUrl(
   fs: FileSystem,
   filename: string,
   contents: string,
-) {
+): Promise<?{|filename: string, map: any, url: string|}> {
   let match = matchSourceMappingURL(contents);
   if (match) {
     let url = match[1].trim();
diff --git a/packages/core/workers/src/Handle.js b/packages/core/workers/src/Handle.js
index 62a4621df..2b643e84d 100644
--- a/packages/core/workers/src/Handle.js
+++ b/packages/core/workers/src/Handle.js
@@ -31,14 +31,14 @@ export default class Handle {
     handleById.delete(this.id);
   }
 
-  serialize() {
+  serialize(): {|childId: ?number, id: number|} {
     return {
       id: this.id,
       childId: this.childId,
     };
   }
 
-  static deserialize(opts: HandleOpts) {
+  static deserialize(opts: HandleOpts): Handle {
     return new Handle(opts);
   }
 }
diff --git a/packages/core/workers/src/Profiler.js b/packages/core/workers/src/Profiler.js
index a5940230a..925de0321 100644
--- a/packages/core/workers/src/Profiler.js
+++ b/packages/core/workers/src/Profiler.js
@@ -40,7 +40,7 @@ type PositionTickInfo = {|
 export default class Profiler {
   session: Session;
 
-  startProfiling() {
+  startProfiling(): Promise<mixed> {
     let inspector;
     try {
       inspector = require('inspector');
diff --git a/packages/core/workers/src/Trace.js b/packages/core/workers/src/Trace.js
index a15f95531..ffd1f83cf 100644
--- a/packages/core/workers/src/Trace.js
+++ b/packages/core/workers/src/Trace.js
@@ -15,7 +15,7 @@ export default class Trace {
     this.init();
   }
 
-  getEventId() {
+  getEventId(): number {
     return this.eventId++;
   }
 
@@ -111,7 +111,7 @@ export default class Trace {
     });
   }
 
-  pipe(writable: Writable) {
+  pipe(writable: Writable): stream$Writable {
     return this.tracer.pipe(writable);
   }
 
diff --git a/packages/core/workers/src/Worker.js b/packages/core/workers/src/Worker.js
index 04adc1ad4..a3c8a24ca 100644
--- a/packages/core/workers/src/Worker.js
+++ b/packages/core/workers/src/Worker.js
@@ -1,7 +1,8 @@
 // @flow
 
 import type {FilePath} from '@parcel/types';
-import type {WorkerMessage, WorkerImpl, BackendType} from './types';
+import type {BackendType, WorkerImpl, WorkerMessage} from './types';
+import type {SharedReference} from './WorkerFarm';
 
 import EventEmitter from 'events';
 import ThrowableDiagnostic from '@parcel/diagnostic';
@@ -20,7 +21,7 @@ type WorkerOpts = {|
   forcedKillTime: number,
   backend: BackendType,
   patchConsole?: boolean,
-  sharedReferences: Map<number, mixed>,
+  sharedReferences: $ReadOnlyMap<SharedReference, mixed>,
 |};
 
 let WORKER_ID = 0;
@@ -28,15 +29,15 @@ export default class Worker extends EventEmitter {
   +options: WorkerOpts;
   worker: WorkerImpl;
   id: number = WORKER_ID++;
-  sharedReferences: Map<number, mixed> = new Map();
+  sharedReferences: $ReadOnlyMap<SharedReference, mixed> = new Map();
 
   calls: Map<number, WorkerCall> = new Map();
-  exitCode = null;
-  callId = 0;
+  exitCode: ?number = null;
+  callId: number = 0;
 
-  ready = false;
-  stopped = false;
-  isStopping = false;
+  ready: boolean = false;
+  stopped: boolean = false;
+  isStopping: boolean = false;
 
   constructor(options: WorkerOpts) {
     super();
@@ -118,7 +119,7 @@ export default class Worker extends EventEmitter {
     this.emit('ready');
   }
 
-  sendSharedReference(ref: number, value: mixed) {
+  sendSharedReference(ref: SharedReference, value: mixed) {
     new Promise((resolve, reject) => {
       this.call({
         method: 'createSharedReference',
diff --git a/packages/core/workers/src/WorkerFarm.js b/packages/core/workers/src/WorkerFarm.js
index be94a7408..214e9cf6d 100644
--- a/packages/core/workers/src/WorkerFarm.js
+++ b/packages/core/workers/src/WorkerFarm.js
@@ -34,6 +34,8 @@ import logger from '@parcel/logger';
 let profileId = 1;
 let referenceId = 1;
 
+export opaque type SharedReference = number;
+
 export type FarmOptions = {|
   maxConcurrentWorkers: number,
   maxConcurrentCallsPerWorker: number,
@@ -52,8 +54,8 @@ type WorkerModule = {|
 export type WorkerApi = {|
   callMaster(CallRequest, ?boolean): Promise<mixed>,
   createReverseHandle(fn: HandleFunction): Handle,
-  getSharedReference(ref: number): mixed,
-  resolveSharedReference(value: mixed): ?number,
+  getSharedReference(ref: SharedReference): mixed,
+  resolveSharedReference(value: mixed): ?SharedReference,
   callChild?: (childId: number, request: HandleCallRequest) => Promise<mixed>,
 |};
 
@@ -72,8 +74,8 @@ export default class WorkerFarm extends EventEmitter {
   warmWorkers: number = 0;
   workers: Map<number, Worker> = new Map();
   handles: Map<number, Handle> = new Map();
-  sharedReferences: Map<number, mixed> = new Map();
-  sharedReferencesByValue: Map<mixed, number> = new Map();
+  sharedReferences: Map<SharedReference, mixed> = new Map();
+  sharedReferencesByValue: Map<mixed, SharedReference> = new Map();
   profiler: ?Profiler;
 
   constructor(farmOptions: $Shape<FarmOptions> = {}) {
@@ -99,7 +101,17 @@ export default class WorkerFarm extends EventEmitter {
     this.startMaxWorkers();
   }
 
-  workerApi = {
+  workerApi: {|
+    callChild: (childId: number, request: HandleCallRequest) => Promise<mixed>,
+    callMaster: (
+      request: CallRequest,
+      awaitResponse?: ?boolean,
+    ) => Promise<mixed>,
+    createReverseHandle: (fn: HandleFunction) => Handle,
+    getSharedReference: (ref: SharedReference) => mixed,
+    resolveSharedReference: (value: mixed) => void | SharedReference,
+    runHandle: (handle: Handle, args: Array<any>) => Promise<mixed>,
+  |} = {
     callMaster: async (
       request: CallRequest,
       awaitResponse: ?boolean = true,
@@ -127,7 +139,8 @@ export default class WorkerFarm extends EventEmitter {
         handle: handle.id,
         args,
       }),
-    getSharedReference: (ref: number) => this.sharedReferences.get(ref),
+    getSharedReference: (ref: SharedReference) =>
+      this.sharedReferences.get(ref),
     resolveSharedReference: (value: mixed) =>
       this.sharedReferencesByValue.get(value),
   };
@@ -180,7 +193,7 @@ export default class WorkerFarm extends EventEmitter {
     };
   }
 
-  onError(error: ErrorWithCode, worker: Worker) {
+  onError(error: ErrorWithCode, worker: Worker): void | Promise<void> {
     // Handle ipc errors
     if (error.code === 'ERR_IPC_CHANNEL_CLOSED') {
       return this.stopWorker(worker);
@@ -369,13 +382,15 @@ export default class WorkerFarm extends EventEmitter {
     );
   }
 
-  createReverseHandle(fn: HandleFunction) {
+  createReverseHandle(fn: HandleFunction): Handle {
     let handle = new Handle({fn});
     this.handles.set(handle.id, handle);
     return handle;
   }
 
-  async createSharedReference(value: mixed) {
+  async createSharedReference(
+    value: mixed,
+  ): Promise<{|ref: SharedReference, dispose(): Promise<mixed>|}> {
     let ref = referenceId++;
     this.sharedReferences.set(ref, value);
     this.sharedReferencesByValue.set(value, ref);
@@ -477,17 +492,26 @@ export default class WorkerFarm extends EventEmitter {
     });
   }
 
-  static getNumWorkers() {
+  static getNumWorkers(): number {
     return process.env.PARCEL_WORKERS
       ? parseInt(process.env.PARCEL_WORKERS, 10)
       : cpuCount();
   }
 
-  static isWorker() {
+  static isWorker(): boolean {
     return !!child;
   }
 
-  static getWorkerApi() {
+  static getWorkerApi(): {|
+    callMaster: (
+      request: CallRequest,
+      awaitResponse?: ?boolean,
+    ) => Promise<mixed>,
+    createReverseHandle: (fn: (...args: Array<any>) => mixed) => Handle,
+    getSharedReference: (ref: SharedReference) => mixed,
+    resolveSharedReference: (value: mixed) => void | SharedReference,
+    runHandle: (handle: Handle, args: Array<any>) => Promise<mixed>,
+  |} {
     invariant(
       child != null,
       'WorkerFarm.getWorkerApi can only be called within workers',
@@ -495,7 +519,7 @@ export default class WorkerFarm extends EventEmitter {
     return child.workerApi;
   }
 
-  static getConcurrentCallsPerWorker() {
+  static getConcurrentCallsPerWorker(): number {
     return parseInt(process.env.PARCEL_MAX_CONCURRENT_CALLS, 10) || 5;
   }
 }
diff --git a/packages/core/workers/src/bus.js b/packages/core/workers/src/bus.js
index b043431a5..fe1945217 100644
--- a/packages/core/workers/src/bus.js
+++ b/packages/core/workers/src/bus.js
@@ -20,4 +20,4 @@ class Bus extends EventEmitter {
   }
 }
 
-export default new Bus();
+export default (new Bus(): Bus);
diff --git a/packages/core/workers/src/child.js b/packages/core/workers/src/child.js
index 56fde0af8..e294d72bd 100644
--- a/packages/core/workers/src/child.js
+++ b/packages/core/workers/src/child.js
@@ -9,8 +9,8 @@ import type {
   WorkerResponse,
   ChildImpl,
 } from './types';
-import type {IDisposable} from '@parcel/types';
-import type {WorkerApi} from './WorkerFarm';
+import type {Async, IDisposable} from '@parcel/types';
+import type {SharedReference, WorkerApi} from './WorkerFarm';
 
 import invariant from 'assert';
 import nullthrows from 'nullthrows';
@@ -30,15 +30,15 @@ export class Child {
   childId: ?number;
   maxConcurrentCalls: number = 10;
   module: ?any;
-  responseId = 0;
+  responseId: number = 0;
   responseQueue: Map<number, ChildCall> = new Map();
   loggerDisposable: IDisposable;
   child: ChildImpl;
   profiler: ?Profiler;
   workerApi: WorkerApi;
   handles: Map<number, Handle> = new Map();
-  sharedReferences: Map<number, mixed> = new Map();
-  sharedReferencesByValue: Map<mixed, number> = new Map();
+  sharedReferences: Map<SharedReference, mixed> = new Map();
+  sharedReferencesByValue: Map<mixed, SharedReference> = new Map();
 
   constructor(ChildBackend: Class<ChildImpl>) {
     this.child = new ChildBackend(
@@ -53,7 +53,16 @@ export class Child {
     });
   }
 
-  workerApi = {
+  workerApi: {|
+    callMaster: (
+      request: CallRequest,
+      awaitResponse?: ?boolean,
+    ) => Promise<mixed>,
+    createReverseHandle: (fn: (...args: Array<any>) => mixed) => Handle,
+    getSharedReference: (ref: SharedReference) => mixed,
+    resolveSharedReference: (value: mixed) => void | SharedReference,
+    runHandle: (handle: Handle, args: Array<any>) => Promise<mixed>,
+  |} = {
     callMaster: (
       request: CallRequest,
       awaitResponse: ?boolean = true,
@@ -62,12 +71,13 @@ export class Child {
       this.createReverseHandle(fn),
     runHandle: (handle: Handle, args: Array<any>): Promise<mixed> =>
       this.workerApi.callMaster({handle: handle.id, args}, true),
-    getSharedReference: (ref: number) => this.sharedReferences.get(ref),
+    getSharedReference: (ref: SharedReference) =>
+      this.sharedReferences.get(ref),
     resolveSharedReference: (value: mixed) =>
       this.sharedReferencesByValue.get(value),
   };
 
-  messageListener(message: WorkerMessage): void | Promise<void> {
+  messageListener(message: WorkerMessage): Async<void> {
     if (message.type === 'response') {
       return this.handleResponse(message);
     } else if (message.type === 'request') {
@@ -244,7 +254,7 @@ export class Child {
     this.loggerDisposable.dispose();
   }
 
-  createReverseHandle(fn: (...args: Array<any>) => mixed) {
+  createReverseHandle(fn: (...args: Array<any>) => mixed): Handle {
     let handle = new Handle({
       fn,
       childId: this.childId,
diff --git a/packages/core/workers/src/cpuCount.js b/packages/core/workers/src/cpuCount.js
index 474d08f62..e62077a9c 100644
--- a/packages/core/workers/src/cpuCount.js
+++ b/packages/core/workers/src/cpuCount.js
@@ -36,7 +36,7 @@ export function detectRealCores(): number {
 }
 
 let cores;
-export default function getCores(bypassCache?: boolean = false) {
+export default function getCores(bypassCache?: boolean = false): number {
   // Do not re-run commands if we already have the count...
   if (cores && !bypassCache) {
     return cores;
diff --git a/packages/core/workers/src/index.js b/packages/core/workers/src/index.js
index 6d008f08d..21fcfb1b5 100644
--- a/packages/core/workers/src/index.js
+++ b/packages/core/workers/src/index.js
@@ -34,4 +34,4 @@ if (!WorkerFarm.isWorker()) {
 export default WorkerFarm;
 export {bus};
 export {Handle} from './WorkerFarm';
-export type {WorkerApi, FarmOptions} from './WorkerFarm';
+export type {WorkerApi, FarmOptions, SharedReference} from './WorkerFarm';
diff --git a/packages/core/workers/src/process/ProcessChild.js b/packages/core/workers/src/process/ProcessChild.js
index 496126973..3f277a3dd 100644
--- a/packages/core/workers/src/process/ProcessChild.js
+++ b/packages/core/workers/src/process/ProcessChild.js
@@ -25,7 +25,7 @@ export default class ProcessChild implements ChildImpl {
     process.on('message', data => this.handleMessage(data));
   }
 
-  handleMessage(data: string) {
+  handleMessage(data: string): void {
     if (data === 'die') {
       return this.stop();
     }
diff --git a/packages/core/workers/src/process/ProcessWorker.js b/packages/core/workers/src/process/ProcessWorker.js
index be5b8c69a..36875028b 100644
--- a/packages/core/workers/src/process/ProcessWorker.js
+++ b/packages/core/workers/src/process/ProcessWorker.js
@@ -34,7 +34,7 @@ export default class ProcessWorker implements WorkerImpl {
     this.onExit = onExit;
   }
 
-  start() {
+  start(): Promise<void> {
     this.child = childProcess.fork(WORKER_PATH, process.argv, {
       execArgv: this.execArgv,
       env: process.env,
diff --git a/packages/core/workers/src/threads/ThreadsWorker.js b/packages/core/workers/src/threads/ThreadsWorker.js
index 19460c2eb..55472bc2a 100644
--- a/packages/core/workers/src/threads/ThreadsWorker.js
+++ b/packages/core/workers/src/threads/ThreadsWorker.js
@@ -32,7 +32,7 @@ export default class ThreadsWorker implements WorkerImpl {
     this.onExit = onExit;
   }
 
-  start() {
+  start(): Promise<void> {
     this.worker = new Worker(WORKER_PATH, {
       execArgv: this.execArgv,
       env: process.env,
@@ -47,7 +47,7 @@ export default class ThreadsWorker implements WorkerImpl {
     });
   }
 
-  stop() {
+  stop(): Promise<void> {
     // In node 12, this returns a promise, but previously it accepted a callback
     // TODO: Pass a callback in earlier versions of Node
     return Promise.resolve(this.worker.terminate());
diff --git a/packages/namers/default/src/DefaultNamer.js b/packages/namers/default/src/DefaultNamer.js
index 3fa106723..842758481 100644
--- a/packages/namers/default/src/DefaultNamer.js
+++ b/packages/namers/default/src/DefaultNamer.js
@@ -10,7 +10,7 @@ import nullthrows from 'nullthrows';
 
 const COMMON_NAMES = new Set(['index', 'src', 'lib']);
 
-export default new Namer({
+export default (new Namer({
   name({bundle, bundleGraph, options}) {
     // If the bundle has an explicit file path given (e.g. by a target), use that.
     if (bundle.filePath != null) {
@@ -99,7 +99,7 @@ export default new Namer({
 
     return name + '.' + bundle.type;
   },
-});
+}): Namer);
 
 function nameFromContent(
   bundle: Bundle,
diff --git a/packages/optimizers/blob-url/src/BlobURLOptimizer.js b/packages/optimizers/blob-url/src/BlobURLOptimizer.js
index 3afe79e4c..50bc76734 100644
--- a/packages/optimizers/blob-url/src/BlobURLOptimizer.js
+++ b/packages/optimizers/blob-url/src/BlobURLOptimizer.js
@@ -3,7 +3,7 @@
 import {Optimizer} from '@parcel/plugin';
 import {blobToString} from '@parcel/utils';
 
-export default new Optimizer({
+export default (new Optimizer({
   async optimize({contents}) {
     // Inspired by webpack's worker plugin:
     // https://github.com/webpack-contrib/worker-loader/blob/b82585a1ddb8ae295fd4b1c302bca6b162665de2/src/workers/InlineWorker.js
@@ -18,4 +18,4 @@ export default new Optimizer({
       )}]))`,
     };
   },
-});
+}): Optimizer);
diff --git a/packages/optimizers/cssnano/src/CSSNanoOptimizer.js b/packages/optimizers/cssnano/src/CSSNanoOptimizer.js
index 44e519420..f974f6ce5 100644
--- a/packages/optimizers/cssnano/src/CSSNanoOptimizer.js
+++ b/packages/optimizers/cssnano/src/CSSNanoOptimizer.js
@@ -6,7 +6,7 @@ import postcss from 'postcss';
 // flowlint-next-line untyped-import:off
 import cssnano from 'cssnano';
 
-export default new Optimizer({
+export default (new Optimizer({
   async optimize({
     bundle,
     contents: prevContents,
@@ -54,4 +54,4 @@ export default new Optimizer({
       map,
     };
   },
-});
+}): Optimizer);
diff --git a/packages/optimizers/data-url/src/DataURLOptimizer.js b/packages/optimizers/data-url/src/DataURLOptimizer.js
index b69b0e498..1d83f91de 100644
--- a/packages/optimizers/data-url/src/DataURLOptimizer.js
+++ b/packages/optimizers/data-url/src/DataURLOptimizer.js
@@ -11,7 +11,7 @@ const fixedEncodeURIComponent = (str: string): string => {
   });
 };
 
-export default new Optimizer({
+export default (new Optimizer({
   async optimize({bundle, contents}) {
     let bufferContents = await blobToBuffer(contents);
     let hasBinaryContent = await isBinaryFile(bufferContents);
@@ -29,4 +29,4 @@ export default new Optimizer({
       contents: `data:${mimeType}${encoding},${content}`,
     };
   },
-});
+}): Optimizer);
diff --git a/packages/optimizers/htmlnano/src/HTMLNanoOptimizer.js b/packages/optimizers/htmlnano/src/HTMLNanoOptimizer.js
index 17f329d9b..c89ef36b0 100644
--- a/packages/optimizers/htmlnano/src/HTMLNanoOptimizer.js
+++ b/packages/optimizers/htmlnano/src/HTMLNanoOptimizer.js
@@ -7,7 +7,7 @@ import {Optimizer} from '@parcel/plugin';
 import posthtml from 'posthtml';
 import path from 'path';
 
-export default new Optimizer({
+export default (new Optimizer({
   async optimize({bundle, contents, map, options}) {
     if (!bundle.env.minify) {
       return {contents, map};
@@ -35,4 +35,4 @@ export default new Optimizer({
         .html,
     };
   },
-});
+}): Optimizer);
diff --git a/packages/optimizers/terser/src/TerserOptimizer.js b/packages/optimizers/terser/src/TerserOptimizer.js
index 910c5ed7a..34cae5640 100644
--- a/packages/optimizers/terser/src/TerserOptimizer.js
+++ b/packages/optimizers/terser/src/TerserOptimizer.js
@@ -9,7 +9,7 @@ import ThrowableDiagnostic from '@parcel/diagnostic';
 
 import path from 'path';
 
-export default new Optimizer({
+export default (new Optimizer({
   async optimize({contents, map, bundle, options, getSourceMapReference}) {
     if (!bundle.env.minify) {
       return {contents, map};
@@ -99,4 +99,4 @@ export default new Optimizer({
 
     return {contents: minifiedContents, map: sourceMap};
   },
-});
+}): Optimizer);
diff --git a/packages/packagers/css/src/CSSPackager.js b/packages/packagers/css/src/CSSPackager.js
index 9a8fff579..a8cff1995 100644
--- a/packages/packagers/css/src/CSSPackager.js
+++ b/packages/packagers/css/src/CSSPackager.js
@@ -10,7 +10,7 @@ import {
   replaceURLReferences,
 } from '@parcel/utils';
 
-export default new Packager({
+export default (new Packager({
   async package({
     bundle,
     bundleGraph,
@@ -98,4 +98,4 @@ export default new Packager({
       map,
     });
   },
-});
+}): Packager);
diff --git a/packages/packagers/html/src/HTMLPackager.js b/packages/packagers/html/src/HTMLPackager.js
index f9e9a1f10..e74583c98 100644
--- a/packages/packagers/html/src/HTMLPackager.js
+++ b/packages/packagers/html/src/HTMLPackager.js
@@ -25,7 +25,7 @@ const metadataContent = new Set([
   'title',
 ]);
 
-export default new Packager({
+export default (new Packager({
   async package({bundle, bundleGraph, getInlineBundleContents}) {
     let assets = [];
     bundle.traverseAssets(asset => {
@@ -81,7 +81,7 @@ export default new Packager({
       map,
     });
   },
-});
+}): Packager);
 
 async function getAssetContent(
   bundleGraph: BundleGraph<NamedBundle>,
diff --git a/packages/packagers/js/src/JSPackager.js b/packages/packagers/js/src/JSPackager.js
index c522e9a8f..59b4ac390 100644
--- a/packages/packagers/js/src/JSPackager.js
+++ b/packages/packagers/js/src/JSPackager.js
@@ -21,7 +21,7 @@ const PRELUDE = fs
   .trim()
   .replace(/;$/, '');
 
-export default new Packager({
+export default (new Packager({
   async package({
     bundle,
     bundleGraph,
@@ -199,7 +199,7 @@ export default new Packager({
       map,
     });
   },
-});
+}): Packager);
 
 function getPrefix(
   bundle: NamedBundle,
diff --git a/packages/packagers/raw-url/src/RawUrlPackager.js b/packages/packagers/raw-url/src/RawUrlPackager.js
index 24d21296f..cd73ce2ba 100644
--- a/packages/packagers/raw-url/src/RawUrlPackager.js
+++ b/packages/packagers/raw-url/src/RawUrlPackager.js
@@ -4,7 +4,7 @@ import assert from 'assert';
 import {Packager} from '@parcel/plugin';
 import {replaceURLReferences} from '@parcel/utils';
 
-export default new Packager({
+export default (new Packager({
   async package({bundle, bundleGraph}) {
     let assets = [];
     bundle.traverseAssets(asset => {
@@ -20,4 +20,4 @@ export default new Packager({
     });
     return {contents};
   },
-});
+}): Packager);
diff --git a/packages/packagers/raw/src/RawPackager.js b/packages/packagers/raw/src/RawPackager.js
index 4069ab216..046dfaa04 100644
--- a/packages/packagers/raw/src/RawPackager.js
+++ b/packages/packagers/raw/src/RawPackager.js
@@ -3,7 +3,7 @@
 import assert from 'assert';
 import {Packager} from '@parcel/plugin';
 
-export default new Packager({
+export default (new Packager({
   package({bundle}) {
     let assets = [];
     bundle.traverseAssets(asset => {
@@ -13,4 +13,4 @@ export default new Packager({
     assert.equal(assets.length, 1, 'Raw bundles must only contain one asset');
     return {contents: assets[0].getStream()};
   },
-});
+}): Packager);
diff --git a/packages/packagers/ts/src/TSPackager.js b/packages/packagers/ts/src/TSPackager.js
index 6e6781e06..b8948b51e 100644
--- a/packages/packagers/ts/src/TSPackager.js
+++ b/packages/packagers/ts/src/TSPackager.js
@@ -3,7 +3,7 @@
 import assert from 'assert';
 import {Packager} from '@parcel/plugin';
 
-export default new Packager({
+export default (new Packager({
   async package({bundle, getSourceMapReference}) {
     let assets = [];
     bundle.traverseAssets(asset => {
@@ -22,4 +22,4 @@ export default new Packager({
 
     return {contents: code, map};
   },
-});
+}): Packager);
diff --git a/packages/reporters/build-metrics/src/BuildMetricsReporter.js b/packages/reporters/build-metrics/src/BuildMetricsReporter.js
index 71906f4bd..8850fd5fc 100644
--- a/packages/reporters/build-metrics/src/BuildMetricsReporter.js
+++ b/packages/reporters/build-metrics/src/BuildMetricsReporter.js
@@ -22,7 +22,7 @@ const getValue = (instanceId: string): TimingValue => {
   return timingsMap.get(instanceId);
 };
 
-export default new Reporter({
+export default (new Reporter({
   async report({event, options}) {
     if (event.type === 'buildProgress') {
       let value = getValue(options.instanceId);
@@ -69,4 +69,4 @@ export default new Reporter({
       );
     }
   },
-});
+}): Reporter);
diff --git a/packages/reporters/bundle-analyzer/src/BundleAnalyzerReporter.js b/packages/reporters/bundle-analyzer/src/BundleAnalyzerReporter.js
index 7ba8c3103..2fd62be54 100644
--- a/packages/reporters/bundle-analyzer/src/BundleAnalyzerReporter.js
+++ b/packages/reporters/bundle-analyzer/src/BundleAnalyzerReporter.js
@@ -8,7 +8,7 @@ import {DefaultMap, generateBuildMetrics} from '@parcel/utils';
 import path from 'path';
 import nullthrows from 'nullthrows';
 
-export default new Reporter({
+export default (new Reporter({
   async report({event, options}) {
     if (
       event.type !== 'buildSuccess' ||
@@ -93,7 +93,7 @@ export default new Reporter({
       }),
     );
   },
-});
+}): Reporter);
 
 type BundleData = {|
   groups: Array<Group>,
diff --git a/packages/reporters/bundle-buddy/src/BundleBuddyReporter.js b/packages/reporters/bundle-buddy/src/BundleBuddyReporter.js
index 6a0ac0932..404bfb782 100644
--- a/packages/reporters/bundle-buddy/src/BundleBuddyReporter.js
+++ b/packages/reporters/bundle-buddy/src/BundleBuddyReporter.js
@@ -3,7 +3,7 @@ import type {NamedBundle} from '@parcel/types';
 import {Reporter} from '@parcel/plugin';
 import path from 'path';
 
-export default new Reporter({
+export default (new Reporter({
   async report({event, options}) {
     if (event.type !== 'buildSuccess' || process.env.BUNDLE_BUDDY == null) {
       return;
@@ -48,4 +48,4 @@ export default new Reporter({
       );
     }
   },
-});
+}): Reporter);
diff --git a/packages/reporters/cli/src/CLIReporter.js b/packages/reporters/cli/src/CLIReporter.js
index 0befada8e..55d2e8953 100644
--- a/packages/reporters/cli/src/CLIReporter.js
+++ b/packages/reporters/cli/src/CLIReporter.js
@@ -161,8 +161,8 @@ async function writeDiagnostic(
   }
 }
 
-export default new Reporter({
+export default (new Reporter({
   report({event, options}) {
     return _report(event, options);
   },
-});
+}): Reporter);
diff --git a/packages/reporters/cli/src/emoji.js b/packages/reporters/cli/src/emoji.js
index ce70fc477..d40d6dd0d 100644
--- a/packages/reporters/cli/src/emoji.js
+++ b/packages/reporters/cli/src/emoji.js
@@ -4,9 +4,9 @@ const supportsEmoji =
   process.platform !== 'win32' || process.env.TERM === 'xterm-256color';
 
 // Fallback symbols for Windows from https://en.wikipedia.org/wiki/Code_page_437
-export const progress = supportsEmoji ? '⏳' : '∞';
-export const success = supportsEmoji ? '✨' : '√';
-export const error = supportsEmoji ? '🚨' : '×';
-export const warning = supportsEmoji ? '⚠️' : '‼';
-export const info = supportsEmoji ? 'ℹ️' : 'ℹ';
-export const hint = supportsEmoji ? '💡' : 'ℹ';
+export const progress: string = supportsEmoji ? '⏳' : '∞';
+export const success: string = supportsEmoji ? '✨' : '√';
+export const error: string = supportsEmoji ? '🚨' : '×';
+export const warning: string = supportsEmoji ? '⚠️' : '‼';
+export const info: string = supportsEmoji ? 'ℹ️' : 'ℹ';
+export const hint: string = supportsEmoji ? '💡' : 'ℹ';
diff --git a/packages/reporters/cli/src/render.js b/packages/reporters/cli/src/render.js
index a6306babe..4cdc6df0e 100644
--- a/packages/reporters/cli/src/render.js
+++ b/packages/reporters/cli/src/render.js
@@ -13,8 +13,9 @@ type ColumnType = {|
   align: PadAlign,
 |};
 
-// $FlowFixMe
-export const isTTY = process.env.NODE_ENV !== 'test' && process.stdout.isTTY;
+export const isTTY: any | boolean | true =
+  // $FlowFixMe
+  process.env.NODE_ENV !== 'test' && process.stdout.isTTY;
 
 let stdout = process.stdout;
 let stderr = process.stderr;
diff --git a/packages/reporters/cli/src/utils.js b/packages/reporters/cli/src/utils.js
index 52a61796a..aa08c2434 100644
--- a/packages/reporters/cli/src/utils.js
+++ b/packages/reporters/cli/src/utils.js
@@ -31,12 +31,16 @@ export function getProgressMessage(event: BuildProgressEvent): ?string {
   return null;
 }
 
-export function getTerminalWidth() {
+export function getTerminalWidth(): any {
   return terminalSize;
 }
 
 // Pad a string with spaces on either side
-export function pad(text: string, length: number, align: PadAlign = 'left') {
+export function pad(
+  text: string,
+  length: number,
+  align: PadAlign = 'left',
+): string {
   let pad = ' '.repeat(length - stringWidth(text));
   if (align === 'right') {
     return pad + text;
@@ -48,14 +52,14 @@ export function pad(text: string, length: number, align: PadAlign = 'left') {
 export function formatFilename(
   filename: string,
   color: (s: string) => string = chalk.reset,
-) {
+): string {
   let dir = path.relative(process.cwd(), path.dirname(filename));
   return (
     chalk.dim(dir + (dir ? path.sep : '')) + color(path.basename(filename))
   );
 }
 
-export function countLines(message: string) {
+export function countLines(message: string): number {
   let {columns} = terminalSize;
 
   return stripAnsi(message)
diff --git a/packages/reporters/dev-server/src/HMRServer.js b/packages/reporters/dev-server/src/HMRServer.js
index 67fcada40..538c4c46f 100644
--- a/packages/reporters/dev-server/src/HMRServer.js
+++ b/packages/reporters/dev-server/src/HMRServer.js
@@ -38,7 +38,7 @@ export default class HMRServer {
     this.options = options;
   }
 
-  start() {
+  start(): any {
     let websocketOptions = {
       /*verifyClient: info => {
           if (!this.options.host) return true;
diff --git a/packages/reporters/dev-server/src/Server.js b/packages/reporters/dev-server/src/Server.js
index ad08605f3..022b628af 100644
--- a/packages/reporters/dev-server/src/Server.js
+++ b/packages/reporters/dev-server/src/Server.js
@@ -9,6 +9,7 @@ import type {
 } from '@parcel/types';
 import type {Diagnostic} from '@parcel/diagnostic';
 import type {FileSystem} from '@parcel/fs';
+import type {HTTPServer} from '@parcel/utils';
 
 import invariant from 'assert';
 import EventEmitter from 'events';
@@ -108,7 +109,7 @@ export default class Server extends EventEmitter {
     );
   }
 
-  respond(req: Request, res: Response) {
+  respond(req: Request, res: Response): mixed {
     let {pathname} = url.parse(req.originalUrl || req.url);
 
     if (pathname == null) {
@@ -177,7 +178,11 @@ export default class Server extends EventEmitter {
     }
   }
 
-  serveDist(req: Request, res: Response, next: NextFunction) {
+  serveDist(
+    req: Request,
+    res: Response,
+    next: NextFunction,
+  ): Promise<void> | Promise<mixed> {
     return this.serve(
       this.options.outputFS,
       this.options.distDir,
@@ -193,7 +198,7 @@ export default class Server extends EventEmitter {
     req: Request,
     res: Response,
     next: NextFunction,
-  ) {
+  ): Promise<mixed> {
     if (req.method !== 'GET' && req.method !== 'HEAD') {
       // method not allowed
       res.statusCode = 405;
@@ -272,7 +277,7 @@ export default class Server extends EventEmitter {
     res.end(TEMPLATE_404);
   }
 
-  send500(req: Request, res: Response) {
+  send500(req: Request, res: Response): void | Response {
     setHeaders(res);
 
     res.setHeader('Content-Type', 'text/html; charset=utf-8');
@@ -296,7 +301,7 @@ export default class Server extends EventEmitter {
   /**
    * Load proxy table from package.json and apply them.
    */
-  async applyProxyTable(app: any) {
+  async applyProxyTable(app: any): Promise<Server> {
     // avoid skipping project root
     const fileInRoot: string = path.join(this.options.projectRoot, '_');
 
@@ -338,7 +343,7 @@ export default class Server extends EventEmitter {
     return this;
   }
 
-  async start() {
+  async start(): Promise<HTTPServer> {
     const finalHandler = (req: Request, res: Response) => {
       this.logAccessIfVerbose(req);
 
diff --git a/packages/reporters/dev-server/src/ServerReporter.js b/packages/reporters/dev-server/src/ServerReporter.js
index 18544da02..e1c48f4a7 100644
--- a/packages/reporters/dev-server/src/ServerReporter.js
+++ b/packages/reporters/dev-server/src/ServerReporter.js
@@ -6,7 +6,7 @@ import Server from './Server';
 
 let servers: Map<number, Server> = new Map();
 let hmrServers: Map<number, HMRServer> = new Map();
-export default new Reporter({
+export default (new Reporter({
   async report({event, options, logger}) {
     let {serve, hot: hmr} = options;
     let server = serve ? servers.get(serve.port) : undefined;
@@ -111,4 +111,4 @@ export default new Reporter({
         break;
     }
   },
-});
+}): Reporter);
diff --git a/packages/reporters/json/src/JSONReporter.js b/packages/reporters/json/src/JSONReporter.js
index 4cf63228b..29d28cf30 100644
--- a/packages/reporters/json/src/JSONReporter.js
+++ b/packages/reporters/json/src/JSONReporter.js
@@ -20,7 +20,7 @@ const LOG_LEVELS = {
   verbose: 4,
 };
 
-export default new Reporter({
+export default (new Reporter({
   async report({event, options}) {
     let logLevelFilter = options.logLevel || 'info';
 
@@ -68,7 +68,7 @@ export default new Reporter({
         writeLogEvent(event, logLevelFilter);
     }
   },
-});
+}): Reporter);
 
 function makeWriter(
   write: string => mixed,
diff --git a/packages/reporters/sourcemap-visualiser/src/SourceMapVisualiser.js b/packages/reporters/sourcemap-visualiser/src/SourceMapVisualiser.js
index 7601054fe..62561f02d 100644
--- a/packages/reporters/sourcemap-visualiser/src/SourceMapVisualiser.js
+++ b/packages/reporters/sourcemap-visualiser/src/SourceMapVisualiser.js
@@ -4,7 +4,7 @@ import nullthrows from 'nullthrows';
 import {Reporter} from '@parcel/plugin';
 import {relativePath} from '@parcel/utils';
 
-export default new Reporter({
+export default (new Reporter({
   async report({event, options, logger}) {
     if (event.type === 'buildSuccess') {
       let bundles = [];
@@ -64,4 +64,4 @@ export default new Reporter({
       });
     }
   },
-});
+}): Reporter);
diff --git a/packages/resolvers/default/src/DefaultResolver.js b/packages/resolvers/default/src/DefaultResolver.js
index 9577fb113..60139ba34 100644
--- a/packages/resolvers/default/src/DefaultResolver.js
+++ b/packages/resolvers/default/src/DefaultResolver.js
@@ -7,7 +7,7 @@ import NodeResolver from '@parcel/node-resolver-core';
 // ex. `imports-loader?$=jquery!./example.js`
 const WEBPACK_IMPORT_REGEX = /\S+-loader\S*!\S+/g;
 
-export default new Resolver({
+export default (new Resolver({
   resolve({dependency, options, filePath}) {
     if (WEBPACK_IMPORT_REGEX.test(dependency.moduleSpecifier)) {
       throw new Error(
@@ -37,4 +37,4 @@ export default new Resolver({
       env: dependency.env,
     });
   },
-});
+}): Resolver);
diff --git a/packages/runtimes/hmr/src/HMRRuntime.js b/packages/runtimes/hmr/src/HMRRuntime.js
index 0427d1eea..a278177cc 100644
--- a/packages/runtimes/hmr/src/HMRRuntime.js
+++ b/packages/runtimes/hmr/src/HMRRuntime.js
@@ -10,7 +10,7 @@ const HMR_RUNTIME = fs.readFileSync(
   'utf8',
 );
 
-export default new Runtime({
+export default (new Runtime({
   apply({bundle, options}) {
     if (bundle.type !== 'js' || !options.hot) {
       return;
@@ -28,4 +28,4 @@ export default new Runtime({
       isEntry: true,
     };
   },
-});
+}): Runtime);
diff --git a/packages/runtimes/js/src/JSRuntime.js b/packages/runtimes/js/src/JSRuntime.js
index c1995b9d4..7f20a76ec 100644
--- a/packages/runtimes/js/src/JSRuntime.js
+++ b/packages/runtimes/js/src/JSRuntime.js
@@ -54,7 +54,7 @@ function getLoaders(
   return null;
 }
 
-export default new Runtime({
+export default (new Runtime({
   apply({bundle, bundleGraph, options}) {
     // Dependency ids in code replaced with referenced bundle names
     // Loader runtime added for bundle groups that don't have a native loader (e.g. HTML/CSS/Worker - isURL?),
@@ -187,7 +187,7 @@ export default new Runtime({
 
     return assets;
   },
-});
+}): Runtime);
 
 function getLoaderRuntimes({
   bundle,
diff --git a/packages/runtimes/react-refresh/src/ReactRefreshRuntime.js b/packages/runtimes/react-refresh/src/ReactRefreshRuntime.js
index 57fe6df7a..600d6d65e 100644
--- a/packages/runtimes/react-refresh/src/ReactRefreshRuntime.js
+++ b/packages/runtimes/react-refresh/src/ReactRefreshRuntime.js
@@ -13,7 +13,7 @@ window.$RefreshSig$ = function() {
   };
 };`;
 
-export default new Runtime({
+export default (new Runtime({
   async apply({bundle, options}) {
     if (
       bundle.type !== 'js' ||
@@ -36,4 +36,4 @@ export default new Runtime({
       }
     }
   },
-});
+}): Runtime);
diff --git a/packages/shared/babel-ast-utils/src/index.js b/packages/shared/babel-ast-utils/src/index.js
index 651f3674d..4b503f714 100644
--- a/packages/shared/babel-ast-utils/src/index.js
+++ b/packages/shared/babel-ast-utils/src/index.js
@@ -44,7 +44,7 @@ export async function generate({
   asset: BaseAsset,
   ast: AST,
   options: PluginOptions,
-|}) {
+|}): Promise<{|content: string, map: ?SourceMap|}> {
   let sourceFileName: string = relativeUrl(options.projectRoot, asset.filePath);
   let generated;
   try {
diff --git a/packages/shared/scope-hoisting/src/concat.js b/packages/shared/scope-hoisting/src/concat.js
index e2646c9d3..f357bc336 100644
--- a/packages/shared/scope-hoisting/src/concat.js
+++ b/packages/shared/scope-hoisting/src/concat.js
@@ -67,7 +67,7 @@ export async function concat({
   bundleGraph: BundleGraph<NamedBundle>,
   options: PluginOptions,
   wrappedAssets: Set<string>,
-|}) {
+|}): Promise<BabelNodeFile> {
   let queue = new PromiseQueue({maxConcurrent: 32});
   bundle.traverse((node, shouldWrap) => {
     switch (node.type) {
diff --git a/packages/shared/scope-hoisting/src/formats/commonjs.js b/packages/shared/scope-hoisting/src/formats/commonjs.js
index 3421f2184..2607eaada 100644
--- a/packages/shared/scope-hoisting/src/formats/commonjs.js
+++ b/packages/shared/scope-hoisting/src/formats/commonjs.js
@@ -142,6 +142,9 @@ export function generateBundleImports(
   from: NamedBundle,
   {bundle, assets}: ExternalBundle,
   path: NodePath<Program>,
+  // Implement an interface consistent with other formats
+  // eslint-disable-next-line no-unused-vars
+  bundleGraph: BundleGraph<NamedBundle>,
 ) {
   let specifiers: Array<ObjectProperty> = [...assets].map(asset => {
     let id = getName(asset, 'init');
@@ -374,7 +377,7 @@ export function generateExports(
   path: NodePath<Program>,
   replacements: Map<Symbol, Symbol>,
   options: PluginOptions,
-) {
+): Set<Symbol> {
   let exported = new Set<Symbol>();
   let statements: Array<ExpressionStatement> = [];
 
diff --git a/packages/shared/scope-hoisting/src/formats/esmodule.js b/packages/shared/scope-hoisting/src/formats/esmodule.js
index 87eb9d853..db7cdcc14 100644
--- a/packages/shared/scope-hoisting/src/formats/esmodule.js
+++ b/packages/shared/scope-hoisting/src/formats/esmodule.js
@@ -41,6 +41,9 @@ export function generateBundleImports(
   from: NamedBundle,
   {bundle, assets}: ExternalBundle,
   path: NodePath<Program>,
+  // Implement an interface consistent with other formats
+  // eslint-disable-next-line no-unused-vars
+  bundleGraph: BundleGraph<NamedBundle>,
 ) {
   let specifiers = [...assets].map(asset => {
     let id = getName(asset, 'init');
@@ -127,7 +130,7 @@ export function generateExports(
   programPath: NodePath<Program>,
   replacements: Map<Symbol, Symbol>,
   options: PluginOptions,
-) {
+): Set<Symbol> {
   // maps the bundles's export symbols to the bindings
   let exportedIdentifiers = new Map<Symbol, Symbol>();
   let entry = bundle.getMainEntry();
diff --git a/packages/shared/scope-hoisting/src/formats/global.js b/packages/shared/scope-hoisting/src/formats/global.js
index 1cb5d8dd8..9983f65c7 100644
--- a/packages/shared/scope-hoisting/src/formats/global.js
+++ b/packages/shared/scope-hoisting/src/formats/global.js
@@ -5,6 +5,7 @@ import type {
   Bundle,
   BundleGraph,
   NamedBundle,
+  PluginOptions,
   Symbol,
 } from '@parcel/types';
 import type {NodePath} from '@babel/traverse';
@@ -77,7 +78,13 @@ export function generateBundleImports(
   }
 }
 
-export function generateExternalImport(_: Bundle, {loc}: ExternalModule) {
+export function generateExternalImport(
+  // eslint-disable-next-line no-unused-vars
+  bundle: Bundle,
+  {loc}: ExternalModule,
+  // eslint-disable-next-line no-unused-vars
+  path: NodePath<Program>,
+) {
   throw getThrowableDiagnosticForNode(
     'External modules are not supported when building for browser',
     loc?.filePath,
@@ -90,7 +97,11 @@ export function generateExports(
   bundle: NamedBundle,
   referencedAssets: Set<Asset>,
   path: NodePath<Program>,
-) {
+  // eslint-disable-next-line no-unused-vars
+  replacements: Map<Symbol, Symbol>,
+  // eslint-disable-next-line no-unused-vars
+  options: PluginOptions,
+): Set<Symbol> {
   let exported = new Set<Symbol>();
   let statements: Array<ExpressionStatement> = [];
 
diff --git a/packages/shared/scope-hoisting/src/generate.js b/packages/shared/scope-hoisting/src/generate.js
index 69896d6d0..7eda60b18 100644
--- a/packages/shared/scope-hoisting/src/generate.js
+++ b/packages/shared/scope-hoisting/src/generate.js
@@ -54,7 +54,7 @@ export function generate({
   ast: File,
   options: PluginOptions,
   referencedAssets: Set<Asset>,
-|}) {
+|}): {|contents: string, map: ?SourceMap|} {
   let interpreter;
   let mainEntry = bundle.getMainEntry();
   if (mainEntry && !bundle.target.env.isBrowser()) {
diff --git a/packages/shared/scope-hoisting/src/utils.js b/packages/shared/scope-hoisting/src/utils.js
index 152ada325..3f8b610fc 100644
--- a/packages/shared/scope-hoisting/src/utils.js
+++ b/packages/shared/scope-hoisting/src/utils.js
@@ -32,7 +32,7 @@ export function getName(
   asset: Asset | MutableAsset,
   type: string,
   ...rest: Array<string>
-) {
+): string {
   return (
     '$' +
     t.toIdentifier(asset.id) +
@@ -51,18 +51,21 @@ export function getIdentifier(
   asset: Asset | MutableAsset,
   type: string,
   ...rest: Array<string>
-) {
+): BabelNodeIdentifier {
   return t.identifier(getName(asset, type, ...rest));
 }
 
-export function getExportIdentifier(asset: Asset | MutableAsset, name: string) {
+export function getExportIdentifier(
+  asset: Asset | MutableAsset,
+  name: string,
+): BabelNodeIdentifier {
   return getIdentifier(asset, 'export', name);
 }
 
 export function needsPrelude(
   bundle: NamedBundle,
   bundleGraph: BundleGraph<NamedBundle>,
-) {
+): boolean {
   if (bundle.env.outputFormat !== 'global') {
     return false;
   }
@@ -85,7 +88,7 @@ export function needsPrelude(
 export function isEntry(
   bundle: NamedBundle,
   bundleGraph: BundleGraph<NamedBundle>,
-) {
+): boolean {
   // If there is no parent JS bundle (e.g. in an HTML page), or environment is isolated (e.g. worker)
   // then this bundle is an "entry"
   return (
@@ -98,7 +101,7 @@ export function isEntry(
 export function isReferenced(
   bundle: NamedBundle,
   bundleGraph: BundleGraph<NamedBundle>,
-) {
+): boolean {
   let isReferenced = false;
   bundle.traverseAssets((asset, _, actions) => {
     // A bundle is potentially referenced if any of its assets is referenced
@@ -275,7 +278,7 @@ export function getThrowableDiagnosticForNode(
     |},
     ...
   },
-) {
+): ThrowableDiagnostic {
   let diagnostic: Diagnostic = {
     message,
     language: 'js',
diff --git a/packages/transformers/babel/src/BabelTransformer.js b/packages/transformers/babel/src/BabelTransformer.js
index 884db397d..46dcdaaad 100644
--- a/packages/transformers/babel/src/BabelTransformer.js
+++ b/packages/transformers/babel/src/BabelTransformer.js
@@ -6,7 +6,7 @@ import semver from 'semver';
 import babel7 from './babel7';
 import {load, preSerialize, postDeserialize} from './config';
 
-export default new Transformer({
+export default (new Transformer({
   async loadConfig({config, options, logger}) {
     await load(config, options, logger);
   },
@@ -46,4 +46,4 @@ export default new Transformer({
   generate({asset, ast, options}) {
     return generate({asset, ast, options});
   },
-});
+}): Transformer);
diff --git a/packages/transformers/babel/src/config.js b/packages/transformers/babel/src/config.js
index 9815a49ad..0ddb60ade 100644
--- a/packages/transformers/babel/src/config.js
+++ b/packages/transformers/babel/src/config.js
@@ -23,7 +23,7 @@ export async function load(
   config: Config,
   options: PluginOptions,
   logger: PluginLogger,
-) {
+): Promise<void> {
   // Don't look for a custom babel config if inside node_modules
   if (!config.isSource) {
     return buildDefaultBabelConfig(options, config);
diff --git a/packages/transformers/babel/src/env.js b/packages/transformers/babel/src/env.js
index 4ddee9ef2..42f82c475 100644
--- a/packages/transformers/babel/src/env.js
+++ b/packages/transformers/babel/src/env.js
@@ -13,7 +13,23 @@ import {enginesToBabelTargets} from './utils';
  * This is done by finding the source module's target engines, and the app's
  * target engines, and doing a diff to include only the necessary plugins.
  */
-export default async function getEnvOptions(config: Config) {
+export default async function getEnvOptions(
+  config: Config,
+): Promise<?{|
+  presets: Array<
+    Array<
+      | string
+      | {|
+          corejs: number,
+          ignoreBrowserslistConfig: boolean,
+          shippedProposals: boolean,
+          targets: BabelTargets,
+          useBuiltIns: string,
+        |},
+    >,
+  >,
+  targets: BabelTargets,
+|}> {
   // Load the target engines for the app and generate a @babel/preset-env config
   let appBabelTargets = enginesToBabelTargets(config.env);
 
diff --git a/packages/transformers/babel/src/jsx.js b/packages/transformers/babel/src/jsx.js
index 46beb1d71..f00320dbe 100644
--- a/packages/transformers/babel/src/jsx.js
+++ b/packages/transformers/babel/src/jsx.js
@@ -1,5 +1,8 @@
 // @flow strict-local
+
 import type {Config, PluginOptions} from '@parcel/types';
+import type {BabelConfig} from './types';
+
 import path from 'path';
 
 const JSX_EXTENSIONS = {
@@ -33,7 +36,7 @@ const JSX_PRAGMA = {
 export default async function getJSXOptions(
   options: PluginOptions,
   config: Config,
-) {
+): Promise<?BabelConfig> {
   if (!config.isSource) {
     return null;
   }
diff --git a/packages/transformers/babel/src/utils.js b/packages/transformers/babel/src/utils.js
index fd547d79f..06c90d7b4 100644
--- a/packages/transformers/babel/src/utils.js
+++ b/packages/transformers/babel/src/utils.js
@@ -72,7 +72,7 @@ export function enginesToBabelTargets(env: Environment): BabelTargets {
 
 // TODO: Replace with `minVersion` (https://github.com/npm/node-semver#ranges-1)
 //       once semver has been upgraded across Parcel.
-export function getMinSemver(version: string) {
+export function getMinSemver(version: string): ?string {
   try {
     let range = new semver.Range(version);
     let sorted = range.set.sort((a, b) => a[0].semver.compare(b[0].semver));
diff --git a/packages/transformers/coffeescript/src/CoffeeScriptTransformer.js b/packages/transformers/coffeescript/src/CoffeeScriptTransformer.js
index 479545d08..337506c6a 100644
--- a/packages/transformers/coffeescript/src/CoffeeScriptTransformer.js
+++ b/packages/transformers/coffeescript/src/CoffeeScriptTransformer.js
@@ -4,7 +4,7 @@ import SourceMap from '@parcel/source-map';
 import coffee from 'coffeescript';
 import {relativeUrl} from '@parcel/utils';
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset, options}) {
     let sourceFileName: string = relativeUrl(
       options.projectRoot,
@@ -33,4 +33,4 @@ export default new Transformer({
 
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/css/src/CSSTransformer.js b/packages/transformers/css/src/CSSTransformer.js
index 96cf6d6cb..22185a6b1 100644
--- a/packages/transformers/css/src/CSSTransformer.js
+++ b/packages/transformers/css/src/CSSTransformer.js
@@ -17,7 +17,7 @@ function canHaveDependencies(filePath: FilePath, code: string) {
   return !/\.css$/.test(filePath) || IMPORT_RE.test(code) || URL_RE.test(code);
 }
 
-export default new Transformer({
+export default (new Transformer({
   canReuseAST({ast}) {
     return ast.type === 'postcss' && semver.satisfies(ast.version, '^7.0.0');
   },
@@ -216,4 +216,4 @@ export default new Transformer({
       map,
     };
   },
-});
+}): Transformer);
diff --git a/packages/transformers/graphql/src/GraphQLTransformer.js b/packages/transformers/graphql/src/GraphQLTransformer.js
index fb7fe1bfa..151f10c20 100644
--- a/packages/transformers/graphql/src/GraphQLTransformer.js
+++ b/packages/transformers/graphql/src/GraphQLTransformer.js
@@ -1,7 +1,7 @@
 // @flow
 import {Transformer} from '@parcel/plugin';
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset, options, resolve}) {
     const {
       parse,
@@ -43,4 +43,4 @@ export default new Transformer({
 
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/html/src/HTMLTransformer.js b/packages/transformers/html/src/HTMLTransformer.js
index ad53b5b94..13d3d9dbe 100644
--- a/packages/transformers/html/src/HTMLTransformer.js
+++ b/packages/transformers/html/src/HTMLTransformer.js
@@ -8,7 +8,7 @@ import semver from 'semver';
 import collectDependencies from './dependencies';
 import extractInlineAssets from './inline';
 
-export default new Transformer({
+export default (new Transformer({
   canReuseAST({ast}) {
     return ast.type === 'posthtml' && semver.satisfies(ast.version, '^0.4.0');
   },
@@ -36,4 +36,4 @@ export default new Transformer({
       content: render(ast.program),
     };
   },
-});
+}): Transformer);
diff --git a/packages/transformers/inline-string/src/InlineStringTransformer.js b/packages/transformers/inline-string/src/InlineStringTransformer.js
index 0a8906d6f..c3a5f6afb 100644
--- a/packages/transformers/inline-string/src/InlineStringTransformer.js
+++ b/packages/transformers/inline-string/src/InlineStringTransformer.js
@@ -2,10 +2,10 @@
 
 import {Transformer} from '@parcel/plugin';
 
-export default new Transformer({
+export default (new Transformer({
   transform({asset}) {
     asset.isInline = true;
     asset.meta.inlineType = 'string';
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/inline/src/InlineTransformer.js b/packages/transformers/inline/src/InlineTransformer.js
index 8a8ccc413..a2a666a37 100644
--- a/packages/transformers/inline/src/InlineTransformer.js
+++ b/packages/transformers/inline/src/InlineTransformer.js
@@ -2,9 +2,9 @@
 
 import {Transformer} from '@parcel/plugin';
 
-export default new Transformer({
+export default (new Transformer({
   transform({asset}) {
     asset.isInline = true;
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/js/src/JSTransformer.js b/packages/transformers/js/src/JSTransformer.js
index d181d20aa..8cf1a42b1 100644
--- a/packages/transformers/js/src/JSTransformer.js
+++ b/packages/transformers/js/src/JSTransformer.js
@@ -36,7 +36,7 @@ function canHaveDependencies(code) {
   );
 }
 
-export default new Transformer({
+export default (new Transformer({
   canReuseAST({ast}) {
     return ast.type === 'babel' && semver.satisfies(ast.version, '^7.0.0');
   },
@@ -172,4 +172,4 @@ export default new Transformer({
   generate({asset, ast, options}) {
     return generate({asset, ast, options});
   },
-});
+}): Transformer);
diff --git a/packages/transformers/js/src/visitors/utils.js b/packages/transformers/js/src/visitors/utils.js
index 95ab0e2ba..4d76718c9 100644
--- a/packages/transformers/js/src/visitors/utils.js
+++ b/packages/transformers/js/src/visitors/utils.js
@@ -16,7 +16,7 @@ import {
 import * as types from '@babel/types';
 import traverse from '@babel/traverse';
 
-export function hasBinding(node: Node | Array<Node>, name: string) {
+export function hasBinding(node: Node | Array<Node>, name: string): boolean {
   if (Array.isArray(node)) {
     return node.some(ancestor => hasBinding(ancestor, name));
   } else if (isProgram(node) || isBlockStatement(node) || isBlock(node)) {
@@ -28,7 +28,9 @@ export function hasBinding(node: Node | Array<Node>, name: string) {
     isArrowFunctionExpression(node)
   ) {
     return (
-      (node.id && node.id.name === name) ||
+      (typeof node.id === 'object' &&
+        node.id != null &&
+        node.id.name === name) ||
       node.params.some(param => isIdentifier(param) && param.name === name)
     );
   } else if (isVariableDeclaration(node)) {
@@ -55,7 +57,7 @@ export function morph(
   }
 }
 
-export function isInFalsyBranch(ancestors: Array<Node>) {
+export function isInFalsyBranch(ancestors: Array<Node>): boolean {
   // Check if any ancestors are if statements
   return ancestors.some((node, index) => {
     if (isIfStatement(node) || isConditionalExpression(node)) {
diff --git a/packages/transformers/json/src/JSONTransformer.js b/packages/transformers/json/src/JSONTransformer.js
index cc1555eb9..1d4d3df45 100644
--- a/packages/transformers/json/src/JSONTransformer.js
+++ b/packages/transformers/json/src/JSONTransformer.js
@@ -3,7 +3,7 @@
 import {Transformer} from '@parcel/plugin';
 import json5 from 'json5';
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset}) {
     asset.type = 'js';
     // Use JSON.parse("...") for faster script parsing, see
@@ -16,4 +16,4 @@ export default new Transformer({
     );
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/jsonld/src/JSONLDTransformer.js b/packages/transformers/jsonld/src/JSONLDTransformer.js
index a8ae30164..0590b686d 100644
--- a/packages/transformers/jsonld/src/JSONLDTransformer.js
+++ b/packages/transformers/jsonld/src/JSONLDTransformer.js
@@ -20,7 +20,7 @@ const SCHEMA_ATTRS = [
   'url',
 ];
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset}) {
     let rawCode = await asset.getCode();
     // allowing any recieved jsonld to be in json5 format
@@ -34,7 +34,7 @@ export default new Transformer({
     asset.setCode(JSON.stringify(jsonCode));
     return [asset];
   },
-});
+}): Transformer);
 
 function extractUrlsFrom(data, asset) {
   if (!data) return null;
diff --git a/packages/transformers/less/src/LessTransformer.js b/packages/transformers/less/src/LessTransformer.js
index 14412bed0..dda67d40a 100644
--- a/packages/transformers/less/src/LessTransformer.js
+++ b/packages/transformers/less/src/LessTransformer.js
@@ -15,7 +15,7 @@ type LessConfig = {
   ...
 };
 
-export default new Transformer({
+export default (new Transformer({
   loadConfig({config}) {
     return load({config});
   },
@@ -73,7 +73,7 @@ export default new Transformer({
 
     return [asset];
   },
-});
+}): Transformer);
 
 function urlPlugin({asset}) {
   return {
diff --git a/packages/transformers/less/src/loadConfig.js b/packages/transformers/less/src/loadConfig.js
index dca7e78ff..ad9e8241e 100644
--- a/packages/transformers/less/src/loadConfig.js
+++ b/packages/transformers/less/src/loadConfig.js
@@ -2,7 +2,7 @@
 import type {Config} from '@parcel/types';
 import path from 'path';
 
-export async function load({config}: {|config: Config|}) {
+export async function load({config}: {|config: Config|}): Promise<void> {
   let configFile = await config.getConfig(['.lessrc', '.lessrc.js'], {
     packageKey: 'less',
   });
diff --git a/packages/transformers/mdx/src/MDXTransformer.js b/packages/transformers/mdx/src/MDXTransformer.js
index 7fae2eaa3..9c3a4d940 100644
--- a/packages/transformers/mdx/src/MDXTransformer.js
+++ b/packages/transformers/mdx/src/MDXTransformer.js
@@ -1,7 +1,7 @@
 // @flow
 import {Transformer} from '@parcel/plugin';
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset, options}) {
     let [mdx, code] = await Promise.all([
       options.packageManager.require('@mdx-js/mdx', asset.filePath, {
@@ -25,4 +25,4 @@ ${compiled}
 
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/postcss/src/PostCSSTransformer.js b/packages/transformers/postcss/src/PostCSSTransformer.js
index a52f68748..1a78b3317 100644
--- a/packages/transformers/postcss/src/PostCSSTransformer.js
+++ b/packages/transformers/postcss/src/PostCSSTransformer.js
@@ -16,7 +16,7 @@ import {load, preSerialize, postDeserialize} from './loadConfig';
 const COMPOSES_RE = /composes:.+from\s*("|').*("|')\s*;?/;
 const FROM_IMPORT_RE = /.+from\s*(?:"|')(.*)(?:"|')\s*;?/;
 
-export default new Transformer({
+export default (new Transformer({
   loadConfig({config, options, logger}) {
     return load({config, options, logger});
   },
@@ -158,7 +158,7 @@ export default new Transformer({
       content: code,
     };
   },
-});
+}): Transformer);
 
 function createLoader(
   asset: MutableAsset,
diff --git a/packages/transformers/postcss/src/loadConfig.js b/packages/transformers/postcss/src/loadConfig.js
index 68d74cc0f..71a9240fa 100644
--- a/packages/transformers/postcss/src/loadConfig.js
+++ b/packages/transformers/postcss/src/loadConfig.js
@@ -48,7 +48,7 @@ async function configHydrator(
     options,
   );
 
-  return config.setResult({
+  config.setResult({
     raw: configFile,
     hydrated: {
       plugins,
@@ -67,7 +67,7 @@ export async function load({
   config: Config,
   options: PluginOptions,
   logger: PluginLogger,
-|}) {
+|}): Promise<void> {
   let configFile: any = await config.getConfig(
     ['.postcssrc', '.postcssrc.json', '.postcssrc.js', 'postcss.config.js'],
     {packageKey: 'postcss'},
@@ -142,6 +142,9 @@ export function preSerialize(config: Config) {
   config.result.hydrated = {};
 }
 
-export function postDeserialize(config: Config, options: PluginOptions) {
+export function postDeserialize(
+  config: Config,
+  options: PluginOptions,
+): Promise<void> {
   return configHydrator(config.result.raw, config, options);
 }
diff --git a/packages/transformers/posthtml/src/PostHTMLTransformer.js b/packages/transformers/posthtml/src/PostHTMLTransformer.js
index e8cc4d337..67b851a16 100644
--- a/packages/transformers/posthtml/src/PostHTMLTransformer.js
+++ b/packages/transformers/posthtml/src/PostHTMLTransformer.js
@@ -10,7 +10,7 @@ import nullthrows from 'nullthrows';
 import semver from 'semver';
 import loadPlugins from './loadPlugins';
 
-export default new Transformer({
+export default (new Transformer({
   async loadConfig({config}) {
     let configFile = await config.getConfig(
       ['.posthtmlrc', '.posthtmlrc.js', 'posthtml.config.js'],
@@ -107,4 +107,4 @@ export default new Transformer({
       content: render(ast.program),
     };
   },
-});
+}): Transformer);
diff --git a/packages/transformers/pug/src/PugTransformer.js b/packages/transformers/pug/src/PugTransformer.js
index 61c30df19..4be6f6b07 100644
--- a/packages/transformers/pug/src/PugTransformer.js
+++ b/packages/transformers/pug/src/PugTransformer.js
@@ -3,7 +3,7 @@
 import path from 'path';
 import {Transformer} from '@parcel/plugin';
 
-export default new Transformer({
+export default (new Transformer({
   async loadConfig({config}) {
     let configFile = await config.getConfig([
       '.pugrc',
@@ -61,4 +61,4 @@ export default new Transformer({
 
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/raw/src/RawTransformer.js b/packages/transformers/raw/src/RawTransformer.js
index 02cb0b4d2..99a091fc2 100644
--- a/packages/transformers/raw/src/RawTransformer.js
+++ b/packages/transformers/raw/src/RawTransformer.js
@@ -2,9 +2,9 @@
 
 import {Transformer} from '@parcel/plugin';
 
-export default new Transformer({
+export default (new Transformer({
   transform({asset}) {
     asset.isIsolated = true;
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/react-refresh-babel/src/ReactRefreshBabelTransformer.js b/packages/transformers/react-refresh-babel/src/ReactRefreshBabelTransformer.js
index df0660a4d..350611522 100644
--- a/packages/transformers/react-refresh-babel/src/ReactRefreshBabelTransformer.js
+++ b/packages/transformers/react-refresh-babel/src/ReactRefreshBabelTransformer.js
@@ -17,7 +17,7 @@ async function shouldExclude(asset, options) {
   }
 }
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset, options}) {
     if (!(await shouldExclude(asset, options))) {
       let reactRefreshBabelPlugin = (
@@ -33,4 +33,4 @@ export default new Transformer({
     }
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/react-refresh-wrap/src/ReactRefreshWrapTransformer.js b/packages/transformers/react-refresh-wrap/src/ReactRefreshWrapTransformer.js
index 011af20ce..050306230 100644
--- a/packages/transformers/react-refresh-wrap/src/ReactRefreshWrapTransformer.js
+++ b/packages/transformers/react-refresh-wrap/src/ReactRefreshWrapTransformer.js
@@ -40,7 +40,7 @@ function shouldExclude(asset, options) {
   );
 }
 
-export default new Transformer({
+export default (new Transformer({
   canReuseAST({ast}) {
     return ast.type === 'babel' && semver.satisfies(ast.version, '^7.0.0');
   },
@@ -85,4 +85,4 @@ export default new Transformer({
   generate({asset, ast, options}) {
     return generate({asset, ast, options});
   },
-});
+}): Transformer);
diff --git a/packages/transformers/sass/src/SassTransformer.js b/packages/transformers/sass/src/SassTransformer.js
index bffdc4794..cca435c76 100644
--- a/packages/transformers/sass/src/SassTransformer.js
+++ b/packages/transformers/sass/src/SassTransformer.js
@@ -8,7 +8,7 @@ import SourceMap from '@parcel/source-map';
 // E.g: ~library/file.sass
 const WEBPACK_ALIAS_RE = /^~[^/]/;
 
-export default new Transformer({
+export default (new Transformer({
   async loadConfig({config, options}) {
     let configFile = await config.getConfig(['.sassrc', '.sassrc.js'], {
       packageKey: 'sass',
@@ -102,7 +102,7 @@ export default new Transformer({
     asset.setCode(css);
     return [asset];
   },
-});
+}): Transformer);
 
 function resolvePathImporter({resolve}) {
   return function(rawUrl, prev, done) {
diff --git a/packages/transformers/stylus/src/StylusTransformer.js b/packages/transformers/stylus/src/StylusTransformer.js
index b2e1093f3..3ddf0d2f1 100644
--- a/packages/transformers/stylus/src/StylusTransformer.js
+++ b/packages/transformers/stylus/src/StylusTransformer.js
@@ -6,7 +6,7 @@ import path from 'path';
 
 const URL_RE = /^(?:url\s*\(\s*)?['"]?(?:[#/]|(?:https?:)?\/\/)/i;
 
-export default new Transformer({
+export default (new Transformer({
   async loadConfig({config}) {
     let configFile = await config.getConfig(['.stylusrc', '.stylusrc.js'], {
       packageKey: 'stylus',
@@ -63,7 +63,7 @@ export default new Transformer({
     asset.meta.hasDependencies = false;
     return [asset];
   },
-});
+}): Transformer);
 
 async function getDependencies(
   code,
diff --git a/packages/transformers/sugarss/src/SugarssTransformer.js b/packages/transformers/sugarss/src/SugarssTransformer.js
index 0a5d5ece3..f66ce95c4 100644
--- a/packages/transformers/sugarss/src/SugarssTransformer.js
+++ b/packages/transformers/sugarss/src/SugarssTransformer.js
@@ -3,7 +3,7 @@
 import {Transformer} from '@parcel/plugin';
 import postcss from 'postcss';
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset, options}) {
     const sugarss = await options.packageManager.require(
       'sugarss',
@@ -20,4 +20,4 @@ export default new Transformer({
     asset.setCode(css);
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/svg-react/src/SvgReactTransformer.js b/packages/transformers/svg-react/src/SvgReactTransformer.js
index c33453124..679b3acf9 100644
--- a/packages/transformers/svg-react/src/SvgReactTransformer.js
+++ b/packages/transformers/svg-react/src/SvgReactTransformer.js
@@ -16,7 +16,7 @@ function getComponentName(filePath) {
   return `Svg${pascalCaseFileName}`;
 }
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset}) {
     let code = await asset.getCode();
     let componentName = getComponentName(asset.filePath);
@@ -33,4 +33,4 @@ export default new Transformer({
 
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/svgo/src/SVGOTransformer.js b/packages/transformers/svgo/src/SVGOTransformer.js
index ea5852300..5ad02e143 100644
--- a/packages/transformers/svgo/src/SVGOTransformer.js
+++ b/packages/transformers/svgo/src/SVGOTransformer.js
@@ -9,7 +9,7 @@ const defaultConfig = {
   plugins: [{prefixIds: true}],
 };
 
-export default new Transformer({
+export default (new Transformer({
   async loadConfig({config}) {
     let configFile = await config.getConfig(
       [
@@ -58,4 +58,4 @@ export default new Transformer({
 
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/toml/src/TOMLTransformer.js b/packages/transformers/toml/src/TOMLTransformer.js
index d92debcb1..d62911b54 100644
--- a/packages/transformers/toml/src/TOMLTransformer.js
+++ b/packages/transformers/toml/src/TOMLTransformer.js
@@ -2,7 +2,7 @@
 
 import {Transformer} from '@parcel/plugin';
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset, options}) {
     const toml = await options.packageManager.require(
       '@iarna/toml',
@@ -19,4 +19,4 @@ export default new Transformer({
     );
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/typescript-tsc/src/TSCTransformer.js b/packages/transformers/typescript-tsc/src/TSCTransformer.js
index 0bc3a231b..e34f46792 100644
--- a/packages/transformers/typescript-tsc/src/TSCTransformer.js
+++ b/packages/transformers/typescript-tsc/src/TSCTransformer.js
@@ -6,7 +6,7 @@ import type {TranspileOptions} from 'typescript';
 import {Transformer} from '@parcel/plugin';
 import {loadTSConfig} from '@parcel/ts-utils';
 
-export default new Transformer({
+export default (new Transformer({
   async loadConfig({config, options}) {
     await loadTSConfig(config, options);
   },
@@ -46,4 +46,4 @@ export default new Transformer({
       },
     ];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/typescript-types/src/TSModule.js b/packages/transformers/typescript-types/src/TSModule.js
index fc88499f6..c33d60e5e 100644
--- a/packages/transformers/typescript-types/src/TSModule.js
+++ b/packages/transformers/typescript-types/src/TSModule.js
@@ -42,11 +42,11 @@ export class TSModule {
     }
   }
 
-  getName(name: string) {
+  getName(name: string): string {
     return this.names.get(name) || name;
   }
 
-  hasBinding(name: string) {
+  hasBinding(name: string): boolean {
     return this.bindings.has(name);
   }
 }
diff --git a/packages/transformers/typescript-types/src/TSModuleGraph.js b/packages/transformers/typescript-types/src/TSModuleGraph.js
index 83ea15f58..35187ca9b 100644
--- a/packages/transformers/typescript-types/src/TSModuleGraph.js
+++ b/packages/transformers/typescript-types/src/TSModuleGraph.js
@@ -24,11 +24,11 @@ export class TSModuleGraph {
     }
   }
 
-  getModule(name: string) {
+  getModule(name: string): ?TSModule {
     return this.modules.get(name);
   }
 
-  markUsed(module: TSModule, name: string, context: any) {
+  markUsed(module: TSModule, name: string, context: any): void {
     let {ts} = this;
 
     // If name is imported, mark used in the original module
@@ -73,7 +73,10 @@ export class TSModuleGraph {
     }
   }
 
-  getExport(m: TSModule, e: Export) {
+  getExport(
+    m: TSModule,
+    e: Export,
+  ): ?{|imported: string, module: TSModule, name: string|} {
     invariant(e.name != null);
     let exportName = e.name;
 
@@ -114,7 +117,11 @@ export class TSModuleGraph {
     };
   }
 
-  resolveImport(module: TSModule, local: string, imported?: string) {
+  resolveImport(
+    module: TSModule,
+    local: string,
+    imported?: string,
+  ): ?{|imported: string, module: TSModule, name: string|} {
     let i = module.imports.get(local);
     if (!i) {
       return null;
@@ -129,7 +136,10 @@ export class TSModuleGraph {
     return this.resolveExport(m, imported || i.imported);
   }
 
-  resolveExport(module: TSModule, name: string) {
+  resolveExport(
+    module: TSModule,
+    name: string,
+  ): ?{|imported: string, module: TSModule, name: string|} {
     for (let e of module.exports) {
       if (e.name === name) {
         return this.getExport(module, e);
@@ -145,7 +155,7 @@ export class TSModuleGraph {
   getAllExports(
     module: TSModule = nullthrows(this.mainModule),
     excludeDefault: boolean = false,
-  ) {
+  ): Array<{|imported: string, module: TSModule, name: string|}> {
     let res = [];
     for (let e of module.exports) {
       if (e.name && (!excludeDefault || e.name !== 'default')) {
@@ -163,7 +173,7 @@ export class TSModuleGraph {
     return res;
   }
 
-  getAllImports() {
+  getAllImports(): Map<string, Map<string, string>> {
     // Build a map of all imports for external modules
     let importsBySpecifier: Map<string, Map<string, string>> = new Map();
     for (let module of this.modules.values()) {
@@ -184,7 +194,7 @@ export class TSModuleGraph {
     return importsBySpecifier;
   }
 
-  propagate(context: any) {
+  propagate(context: any): Map<string, TSModule> {
     // Resolve all exported values, and mark them as used.
     let names = Object.create(null);
     let exportedNames = new Map<string, TSModule>();
diff --git a/packages/transformers/typescript-types/src/TSTypesTransformer.js b/packages/transformers/typescript-types/src/TSTypesTransformer.js
index ff5fdabca..901ffd51f 100644
--- a/packages/transformers/typescript-types/src/TSTypesTransformer.js
+++ b/packages/transformers/typescript-types/src/TSTypesTransformer.js
@@ -13,7 +13,7 @@ import nullthrows from 'nullthrows';
 import {collect} from './collect';
 import {shake} from './shake';
 
-export default new Transformer({
+export default (new Transformer({
   async loadConfig({config, options}) {
     await loadTSConfig(config, options);
   },
@@ -154,4 +154,4 @@ export default new Transformer({
       },
     ];
   },
-});
+}): Transformer);
diff --git a/packages/transformers/typescript-types/src/collect.js b/packages/transformers/typescript-types/src/collect.js
index 4de26c263..1cd97bbb6 100644
--- a/packages/transformers/typescript-types/src/collect.js
+++ b/packages/transformers/typescript-types/src/collect.js
@@ -9,7 +9,7 @@ export function collect(
   moduleGraph: TSModuleGraph,
   context: any,
   sourceFile: any,
-) {
+): any {
   let currentModule: ?TSModule;
   let visit = (node: any): any => {
     if (ts.isBundle(node)) {
diff --git a/packages/transformers/typescript-types/src/shake.js b/packages/transformers/typescript-types/src/shake.js
index 7b69751a3..a8f785c33 100644
--- a/packages/transformers/typescript-types/src/shake.js
+++ b/packages/transformers/typescript-types/src/shake.js
@@ -10,7 +10,7 @@ export function shake(
   moduleGraph: TSModuleGraph,
   context: any,
   sourceFile: any,
-) {
+): any {
   // We traverse things out of order which messes with typescript's internal state.
   // We don't rely on the lexical environment, so just overwrite with noops to avoid errors.
   context.suspendLexicalEnvironment = () => {};
diff --git a/packages/transformers/typescript-types/src/utils.js b/packages/transformers/typescript-types/src/utils.js
index f53828410..7178997f3 100644
--- a/packages/transformers/typescript-types/src/utils.js
+++ b/packages/transformers/typescript-types/src/utils.js
@@ -1,7 +1,7 @@
 // @flow
 import typeof TypeScriptModule from 'typescript'; // eslint-disable-line import/no-extraneous-dependencies
 
-export function getExportedName(ts: TypeScriptModule, node: any) {
+export function getExportedName(ts: TypeScriptModule, node: any): ?string {
   if (!node.modifiers) {
     return null;
   }
@@ -17,7 +17,7 @@ export function getExportedName(ts: TypeScriptModule, node: any) {
   return node.name.text;
 }
 
-export function isDeclaration(ts: TypeScriptModule, node: any) {
+export function isDeclaration(ts: TypeScriptModule, node: any): boolean {
   return (
     ts.isFunctionDeclaration(node) ||
     ts.isClassDeclaration(node) ||
diff --git a/packages/transformers/yaml/src/YAMLTransformer.js b/packages/transformers/yaml/src/YAMLTransformer.js
index 74c977184..14a26ab17 100644
--- a/packages/transformers/yaml/src/YAMLTransformer.js
+++ b/packages/transformers/yaml/src/YAMLTransformer.js
@@ -2,7 +2,7 @@
 
 import {Transformer} from '@parcel/plugin';
 
-export default new Transformer({
+export default (new Transformer({
   async transform({asset, options}) {
     const yaml = await options.packageManager.require(
       'js-yaml',
@@ -19,4 +19,4 @@ export default new Transformer({
     );
     return [asset];
   },
-});
+}): Transformer);
diff --git a/packages/utils/events/src/Disposable.js b/packages/utils/events/src/Disposable.js
index 0293cc4bf..2c55b0ae3 100644
--- a/packages/utils/events/src/Disposable.js
+++ b/packages/utils/events/src/Disposable.js
@@ -14,7 +14,7 @@ type DisposableLike = IDisposable | (() => mixed);
  */
 export default class Disposable implements IDisposable {
   disposed: boolean = false;
-  #disposables; // ?Set<DisposableLike>
+  #disposables /*: ?Set<DisposableLike> */;
 
   constructor(...disposables: Array<DisposableLike>) {
     this.#disposables = new Set(disposables);
diff --git a/packages/utils/node-resolver-core/src/NodeResolver.js b/packages/utils/node-resolver-core/src/NodeResolver.js
index 5e16b5c58..d6f2a29d3 100644
--- a/packages/utils/node-resolver-core/src/NodeResolver.js
+++ b/packages/utils/node-resolver-core/src/NodeResolver.js
@@ -43,7 +43,7 @@ type Aliases =
   | {[string]: string | boolean, ...};
 type Module = {|
   moduleName?: string,
-  subPath?: string,
+  subPath?: ?string,
   moduleDir?: FilePath,
   filePath?: FilePath,
   code?: string,
@@ -203,7 +203,7 @@ export default class NodeResolver {
     basedir: string,
     maxlength: number,
     collected: Array<string>,
-  |}) {
+  |}): Promise<mixed> {
     let dirContent = await this.options.inputFS.readdir(dir);
     return Promise.all(
       dirContent.map(async item => {
@@ -367,7 +367,10 @@ export default class NodeResolver {
     return resolved;
   }
 
-  shouldIncludeNodeModule({includeNodeModules}: Environment, name: string) {
+  shouldIncludeNodeModule(
+    {includeNodeModules}: Environment,
+    name: string,
+  ): boolean {
     if (includeNodeModules === false) {
       return false;
     }
@@ -388,7 +391,11 @@ export default class NodeResolver {
     return true;
   }
 
-  async resolveFilename(filename: string, dir: string, isURL: ?boolean) {
+  async resolveFilename(
+    filename: string,
+    dir: string,
+    isURL: ?boolean,
+  ): Promise<string> {
     switch (filename[0]) {
       case '/': {
         // Absolute path. Resolve relative to project root.
@@ -483,7 +490,7 @@ export default class NodeResolver {
     return resolvedFile;
   }
 
-  findBuiltin(filename: string, env: Environment) {
+  findBuiltin(filename: string, env: Environment): ?Module {
     if (builtins[filename]) {
       if (env.isNode()) {
         return null;
@@ -493,7 +500,7 @@ export default class NodeResolver {
     }
   }
 
-  async findNodeModulePath(filename: string, dir: string) {
+  async findNodeModulePath(filename: string, dir: string): Promise<?Module> {
     let [moduleName, subPath] = this.getModuleParts(filename);
     let root = path.parse(dir).root;
 
@@ -530,7 +537,7 @@ export default class NodeResolver {
     module: Module,
     extensions: Array<string>,
     env: Environment,
-  ) {
+  ): Promise<?ResolvedFile> {
     // If a module was specified as a module sub-path (e.g. some-module/some/path),
     // it is likely a file. Try loading it as a file first.
     if (module.subPath && module.moduleDir) {
@@ -554,7 +561,7 @@ export default class NodeResolver {
     });
   }
 
-  async isFile(file: FilePath) {
+  async isFile(file: FilePath): Promise<boolean> {
     try {
       let stat = await this.options.inputFS.stat(file);
       return stat.isFile() || stat.isFIFO();
@@ -792,7 +799,7 @@ export default class NodeResolver {
     filename: string,
     env: Environment,
     pkg: InternalPackageJSON | null,
-  ) {
+  ): Promise<string | Array<string>> {
     let localAliases = await this.resolvePackageAliases(filename, env, pkg);
     if (Array.isArray(localAliases) || typeof localAliases === 'boolean') {
       return localAliases;
@@ -806,7 +813,7 @@ export default class NodeResolver {
     filename: string,
     env: Environment,
     pkg: InternalPackageJSON | null,
-  ) {
+  ): Promise<string | Array<string>> {
     if (!pkg) {
       return filename;
     }
@@ -821,7 +828,11 @@ export default class NodeResolver {
     return filename;
   }
 
-  async getAlias(filename: FilePath, dir: FilePath, aliases: ?Aliases) {
+  async getAlias(
+    filename: FilePath,
+    dir: FilePath,
+    aliases: ?Aliases,
+  ): Promise<null | Array<string>> {
     if (!filename || !aliases || typeof aliases !== 'object') {
       return null;
     }
@@ -875,7 +886,7 @@ export default class NodeResolver {
     return null;
   }
 
-  lookupAlias(aliases: Aliases, filename: FilePath) {
+  lookupAlias(aliases: Aliases, filename: FilePath): null | boolean | string {
     if (typeof aliases !== 'object') {
       return null;
     }
@@ -898,7 +909,7 @@ export default class NodeResolver {
     return alias;
   }
 
-  async findPackage(dir: string) {
+  async findPackage(dir: string): Promise<InternalPackageJSON | null> {
     // Find the nearest package.json file within the current node_modules folder
     let root = path.parse(dir).root;
     while (dir !== root && path.basename(dir) !== 'node_modules') {
@@ -914,7 +925,11 @@ export default class NodeResolver {
     return null;
   }
 
-  async loadAlias(filename: string, dir: string, env: Environment) {
+  async loadAlias(
+    filename: string,
+    dir: string,
+    env: Environment,
+  ): Promise<string | Array<string>> {
     // Load the root project's package.json file if we haven't already
     if (!this.rootPackage) {
       this.rootPackage = await this.findPackage(this.options.rootDir);
@@ -925,7 +940,7 @@ export default class NodeResolver {
     return this.resolveAliases(filename, env, pkg);
   }
 
-  getModuleParts(name: string) {
+  getModuleParts(name: string): [FilePath, ?string] {
     name = path.normalize(name);
     let splitOn = name.indexOf(path.sep);
     if (name.charAt(0) === '@') {
diff --git a/packages/utils/ts-utils/src/CompilerHost.js b/packages/utils/ts-utils/src/CompilerHost.js
index 09e08b096..72f330709 100644
--- a/packages/utils/ts-utils/src/CompilerHost.js
+++ b/packages/utils/ts-utils/src/CompilerHost.js
@@ -1,6 +1,6 @@
 // @flow
 import type {FilePath} from '@parcel/types';
-import type {CompilerOptions} from 'typescript';
+import type {CompilerOptions, SourceFile} from 'typescript';
 import typeof {ScriptTarget} from 'typescript'; // eslint-disable-line import/no-extraneous-dependencies
 import path from 'path';
 import {FSHost} from './FSHost';
@@ -9,14 +9,17 @@ export class CompilerHost extends FSHost {
   outputCode: ?string;
   outputMap: ?string;
 
-  getSourceFile(filePath: FilePath, languageVersion: $Values<ScriptTarget>) {
+  getSourceFile(
+    filePath: FilePath,
+    languageVersion: $Values<ScriptTarget>,
+  ): void | SourceFile {
     const sourceText = this.readFile(filePath);
     return sourceText !== undefined
       ? this.ts.createSourceFile(filePath, sourceText, languageVersion)
       : undefined;
   }
 
-  getDefaultLibFileName(options: CompilerOptions) {
+  getDefaultLibFileName(options: CompilerOptions): string {
     return this.ts.getDefaultLibFilePath(options);
   }
 
@@ -28,17 +31,17 @@ export class CompilerHost extends FSHost {
     }
   }
 
-  getCanonicalFileName(fileName: FilePath) {
+  getCanonicalFileName(fileName: FilePath): FilePath | string {
     return this.ts.sys.useCaseSensitiveFileNames
       ? fileName
       : fileName.toLowerCase();
   }
 
-  useCaseSensitiveFileNames() {
+  useCaseSensitiveFileNames(): boolean {
     return this.ts.sys.useCaseSensitiveFileNames;
   }
 
-  getNewLine() {
+  getNewLine(): string {
     return this.ts.sys.newLine;
   }
 }
diff --git a/packages/utils/ts-utils/src/FSHost.js b/packages/utils/ts-utils/src/FSHost.js
index 70ab63a9f..c7e571933 100644
--- a/packages/utils/ts-utils/src/FSHost.js
+++ b/packages/utils/ts-utils/src/FSHost.js
@@ -13,11 +13,11 @@ export class FSHost {
     this.ts = ts;
   }
 
-  getCurrentDirectory() {
+  getCurrentDirectory(): FilePath {
     return this.fs.cwd();
   }
 
-  fileExists(filePath: FilePath) {
+  fileExists(filePath: FilePath): boolean {
     try {
       return this.fs.statSync(filePath).isFile();
     } catch (err) {
@@ -25,7 +25,7 @@ export class FSHost {
     }
   }
 
-  readFile(filePath: FilePath) {
+  readFile(filePath: FilePath): void | string {
     try {
       return this.fs.readFileSync(filePath, 'utf8');
     } catch (err) {
@@ -37,7 +37,7 @@ export class FSHost {
     }
   }
 
-  directoryExists(filePath: FilePath) {
+  directoryExists(filePath: FilePath): boolean {
     try {
       return this.fs.statSync(filePath).isDirectory();
     } catch (err) {
@@ -45,7 +45,7 @@ export class FSHost {
     }
   }
 
-  realpath(filePath: FilePath) {
+  realpath(filePath: FilePath): FilePath {
     try {
       return this.fs.realpathSync(filePath);
     } catch (err) {
@@ -53,7 +53,9 @@ export class FSHost {
     }
   }
 
-  getAccessibleFileSystemEntries(dirPath: FilePath) {
+  getAccessibleFileSystemEntries(
+    dirPath: FilePath,
+  ): {|directories: Array<FilePath>, files: Array<FilePath>|} {
     try {
       let entries = this.fs.readdirSync(dirPath || '.').sort();
       let files = [];
@@ -87,7 +89,7 @@ export class FSHost {
     excludes: ?$ReadOnlyArray<string>,
     includes: $ReadOnlyArray<string>,
     depth?: number,
-  ) {
+  ): any {
     // $FlowFixMe
     return this.ts.matchFiles(
       root,
diff --git a/packages/utils/ts-utils/src/LanguageServiceHost.js b/packages/utils/ts-utils/src/LanguageServiceHost.js
index 5f2312918..93fbc4865 100644
--- a/packages/utils/ts-utils/src/LanguageServiceHost.js
+++ b/packages/utils/ts-utils/src/LanguageServiceHost.js
@@ -2,7 +2,11 @@
 import type {FileSystem} from '@parcel/fs';
 import type {FilePath} from '@parcel/types';
 import typeof TypeScriptModule from 'typescript'; // eslint-disable-line import/no-extraneous-dependencies
-import type {ParsedCommandLine} from 'typescript';
+import type {
+  CompilerOptions,
+  IScriptSnapshot,
+  ParsedCommandLine,
+} from 'typescript';
 import {FSHost} from './FSHost';
 
 export class LanguageServiceHost extends FSHost {
@@ -30,15 +34,15 @@ export class LanguageServiceHost extends FSHost {
     }
   }
 
-  getScriptFileNames() {
+  getScriptFileNames(): Array<string> {
     return this.config.fileNames;
   }
 
-  getScriptVersion(fileName: FilePath) {
+  getScriptVersion(fileName: FilePath): string {
     return this.files[fileName] && this.files[fileName].version.toString();
   }
 
-  getScriptSnapshot(fileName: string) {
+  getScriptSnapshot(fileName: string): IScriptSnapshot | void {
     if (!this.fileExists(fileName)) {
       return;
     }
@@ -51,11 +55,11 @@ export class LanguageServiceHost extends FSHost {
     }
   }
 
-  getCompilationSettings() {
+  getCompilationSettings(): CompilerOptions {
     return this.config.options;
   }
 
-  getDefaultLibFileName(projectOptions: any) {
+  getDefaultLibFileName(projectOptions: any): string {
     return this.ts.getDefaultLibFilePath(projectOptions);
   }
 }
diff --git a/packages/utils/ts-utils/src/ParseConfigHost.js b/packages/utils/ts-utils/src/ParseConfigHost.js
index 92b72311d..0f903e119 100644
--- a/packages/utils/ts-utils/src/ParseConfigHost.js
+++ b/packages/utils/ts-utils/src/ParseConfigHost.js
@@ -14,7 +14,7 @@ export class ParseConfigHost extends FSHost {
     this.useCaseSensitiveFileNames = ts.sys.useCaseSensitiveFileNames;
   }
 
-  readFile(filePath: FilePath) {
+  readFile(filePath: FilePath): void | string {
     this.filesRead.add(filePath);
     return super.readFile(filePath);
   }
diff --git a/packages/validators/eslint/src/EslintValidator.js b/packages/validators/eslint/src/EslintValidator.js
index 109d064b9..1ea69dbab 100644
--- a/packages/validators/eslint/src/EslintValidator.js
+++ b/packages/validators/eslint/src/EslintValidator.js
@@ -4,7 +4,7 @@ import type {DiagnosticCodeFrame} from '@parcel/diagnostic';
 
 let cliEngine = null;
 
-export default new Validator({
+export default (new Validator({
   async validate({asset, options}) {
     let eslint = await options.packageManager.require(
       'eslint',
@@ -65,4 +65,4 @@ export default new Validator({
 
     return validatorResult;
   },
-});
+}): Validator);
diff --git a/packages/validators/typescript/src/TypeScriptValidator.js b/packages/validators/typescript/src/TypeScriptValidator.js
index 977112fba..461fb2ef4 100644
--- a/packages/validators/typescript/src/TypeScriptValidator.js
+++ b/packages/validators/typescript/src/TypeScriptValidator.js
@@ -29,7 +29,7 @@ type TSValidatorConfig = {|
   tsconfig: ConfigResult | null,
 |};
 
-export default new Validator({
+export default (new Validator({
   async validateAll({
     assets,
     options,
@@ -75,7 +75,7 @@ export default new Validator({
 
     return validatorResults;
   },
-});
+}): Validator);
 
 async function getConfig(
   asset,
diff --git a/yarn.lock b/yarn.lock
index dd71ea96f..8d7a1f723 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6154,10 +6154,10 @@ flatten@^1.0.2:
   resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
   integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==
 
-flow-bin@0.124.0:
-  version "0.124.0"
-  resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.124.0.tgz#24b2e55874e1e2041f9247f42473b3db2ef32758"
-  integrity sha512-KEtDJ7CFUjcuhw6N52FTZshDd1krf1fxpp4APSIrwhVm+IrlcKJ+EMXpeXKM1kKNSZ347dYGh8wEvXQl4pHZEA==
+flow-bin@0.129.0:
+  version "0.129.0"
+  resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.129.0.tgz#50294d6e335dd97d095c27b096ea0b94c2415d55"
+  integrity sha512-WLXOj09oCK6nODVKM5uxvAzBpxXeI304E60tELMeQd/TJsyfbykNCZ+e4xml9eUOyoac9nDL3YrJpPZMzq0tMA==
 
 flush-write-stream@^1.0.0, flush-write-stream@^1.0.2:
   version "1.1.1"


Test patch:
diff --git a/packages/core/core/test/AssetGraphBuilder.test.js b/packages/core/core/test/AssetGraphBuilder.test.js
index d3e579742..238817c00 100644
--- a/packages/core/core/test/AssetGraphBuilder.test.js
+++ b/packages/core/core/test/AssetGraphBuilder.test.js
@@ -26,6 +26,7 @@ describe('AssetGraphBuilder', function() {
     await builder.init({
       name: 'test',
       options: DEFAULT_OPTIONS,
+      // $FlowFixMe opaque type
       optionsRef: 1,
       entries: ['./module-b'],
       workerFarm,
diff --git a/packages/core/core/test/test-utils.js b/packages/core/core/test/test-utils.js
index 3a0b61f7a..362c230f3 100644
--- a/packages/core/core/test/test-utils.js
+++ b/packages/core/core/test/test-utils.js
@@ -1,6 +1,6 @@
 // @flow
 
-import type {ParcelOptions} from '../src/types';
+import type {Environment, ParcelOptions} from '../src/types';
 
 import Cache, {createCacheDir} from '@parcel/cache';
 import tempy from 'tempy';
@@ -10,7 +10,7 @@ import {createEnvironment} from '../src/Environment';
 
 let cacheDir = tempy.directory();
 createCacheDir(outputFS, cacheDir);
-export let cache = new Cache(outputFS, cacheDir);
+export let cache: Cache = new Cache(outputFS, cacheDir);
 
 export const DEFAULT_OPTIONS: ParcelOptions = {
   cacheDir: '.parcel-cache',
@@ -41,7 +41,7 @@ export const DEFAULT_OPTIONS: ParcelOptions = {
   instanceId: 'test',
 };
 
-export const DEFAULT_ENV = createEnvironment({
+export const DEFAULT_ENV: Environment = createEnvironment({
   context: 'browser',
   engines: {
     browsers: ['> 1%'],
diff --git a/packages/core/test-utils/src/utils.js b/packages/core/test-utils/src/utils.js
index d44fb69dd..274fad0bd 100644
--- a/packages/core/test-utils/src/utils.js
+++ b/packages/core/test-utils/src/utils.js
@@ -27,9 +27,9 @@ import resolve from 'resolve';
 import {NodePackageManager} from '@parcel/package-manager';
 
 const workerFarm = createWorkerFarm();
-export const inputFS = new NodeFS();
-export let outputFS = new MemoryFS(workerFarm);
-export let overlayFS = new OverlayFS(outputFS, inputFS);
+export const inputFS: NodeFS = new NodeFS();
+export let outputFS: MemoryFS = new MemoryFS(workerFarm);
+export let overlayFS: OverlayFS = new OverlayFS(outputFS, inputFS);
 
 beforeEach(() => {
   outputFS = new MemoryFS(workerFarm);
@@ -52,8 +52,8 @@ export async function ncp(source: FilePath, destination: FilePath) {
 
 export const defaultConfig = {
   ...defaultConfigContents,
-  filePath: require.resolve('@parcel/config-default'),
-  reporters: [],
+  filePath: (require.resolve('@parcel/config-default'): string),
+  reporters: ([]: Array<any>),
 };
 
 const chalk = new _chalk.constructor({enabled: true});
@@ -71,11 +71,11 @@ export function sleep(ms: number): Promise<void> {
   return new Promise(resolve => setTimeout(resolve, ms));
 }
 
-export function normalizeFilePath(filePath: string) {
+export function normalizeFilePath(filePath: string): FilePath {
   return normalizeSeparators(filePath);
 }
 
-export const distDir = path.resolve(
+export const distDir: string = path.resolve(
   __dirname,
   '..',
   '..',
@@ -101,7 +101,7 @@ If you don't know how, check here: https://bit.ly/2UmWsbD
 export function bundler(
   entries: FilePath | Array<FilePath>,
   opts?: InitialParcelOptions,
-) {
+): Parcel {
   return new Parcel({
     entries,
     disableCache: true,
@@ -569,7 +569,7 @@ function prepareNodeContext(filePath, globals) {
 export function shallowEqual(
   a: $Shape<{|+[string]: mixed|}>,
   b: $Shape<{|+[string]: mixed|}>,
-) {
+): boolean {
   if (Object.keys(a).length !== Object.keys(b).length) {
     return false;
   }