diff --git a/.eslintignore b/.eslintignore
index c44555219bdf3cead542732f34aa3aabd94d1b44..0434a7df0d92925c05f6643256c27f99cde93a2e 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,3 +1,11 @@
+# don't ever lint node_modules
+node_modules
+# don't lint build output (make sure it's set to your correct build folder name)
+dist
+# don't lint nyc coverage output
+coverage
+
+# don't lint test stuff
 test/**/**/_fixtures
 lib/types/**/*.d.ts
 **/__mocks__/**/*.ts
diff --git a/.eslintrc.js b/.eslintrc.js
index 378cc3c8eb2e229ac92487d883d6f7f2f8183a8a..6d5952d4900c022df6021ce05e26842d4c5668c8 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,38 +1,54 @@
 module.exports = {
+  root: true,
   env: {
     node: true,
-    jest: true,
   },
   extends: [
-    'plugin:promise/recommended',
-    'plugin:@typescript-eslint/recommended',
     'airbnb-typescript/base',
+    'plugin:@typescript-eslint/recommended',
+    // TODO: enable in separate PR
+    // 'plugin:@typescript-eslint/recommended-requiring-type-checking',
+    'plugin:promise/recommended',
     'prettier',
     'prettier/@typescript-eslint',
   ],
   parserOptions: {
     ecmaVersion: 9,
-    project: './tsconfig.json',
+    tsconfigRootDir: __dirname,
+    project: ['./tsconfig.json'],
   },
   rules: {
-    'import/no-unresolved': 0, // done by typescript
+    /*
+     * checks done by typescript.
+     *
+     * https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md#eslint-plugin-import
+     */
+    'import/default': 0,
+    'import/named': 0,
+    'import/namespace': 0,
+    'import/no-named-as-default-member': 0,
+
+    // other rules
     'import/prefer-default-export': 0, // no benefit
     'require-await': 'error',
-    'no-use-before-define': 0,
     'no-restricted-syntax': 0,
     'no-await-in-loop': 0,
-    'prefer-destructuring': 'off',
-    'prefer-template': 'off',
+    'prefer-destructuring': 0,
+    'prefer-template': 0,
     'no-underscore-dangle': 0,
 
-    '@typescript-eslint/explicit-function-return-type': 'error',
+    // Makes no sense to allow type inferrence for expression parameters, but require typing the response
+    '@typescript-eslint/explicit-function-return-type': [
+      'error',
+      { allowExpressions: true, allowTypedFunctionExpressions: true },
+    ],
 
     // TODO: fix lint
-    '@typescript-eslint/camelcase': 'off', // disabled until ??
+    '@typescript-eslint/camelcase': 0, // disabled until ??
     '@typescript-eslint/no-explicit-any': 0,
     '@typescript-eslint/no-non-null-assertion': 0,
     '@typescript-eslint/no-unused-vars': [
-      'error',
+      2,
       {
         vars: 'all',
         args: 'none',
@@ -42,11 +58,18 @@ module.exports = {
   },
   overrides: [
     {
-      files: ['*.js'],
+      files: ['**/*.spec.ts'],
+      env: {
+        jest: true,
+      },
       rules: {
+        'prefer-destructuring': 0,
+        'prefer-promise-reject-errors': 0,
+        'import/no-dynamic-require': 0,
+        'global-require': 0,
+
         '@typescript-eslint/no-var-requires': 0,
-        '@typescript-eslint/no-use-before-define': 0,
-        '@typescript-eslint/explicit-member-accessibility': 0,
+        '@typescript-eslint/no-object-literal-type-assertion': 0,
         '@typescript-eslint/explicit-function-return-type': 0,
       },
     },
diff --git a/lib/.eslintrc.js b/lib/.eslintrc.js
deleted file mode 100644
index 23aed689888c419792ffff066cdb909c65a31e9d..0000000000000000000000000000000000000000
--- a/lib/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
-  globals: {
-    renovateCache: true,
-  },
-};
diff --git a/lib/config/.eslintrc.js b/lib/config/.eslintrc.js
deleted file mode 100644
index 8bcc65cc06d65e68d5207c000f5167759c3b1dcd..0000000000000000000000000000000000000000
--- a/lib/config/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
-  rules: {
-    '@typescript-eslint/explicit-function-return-type': 2,
-  },
-};
diff --git a/lib/manager/npm/extract/common.ts b/lib/manager/npm/extract/common.ts
index cd8bca151f352341683d00eaad2513c29069f70c..e7300c1d403f2f12b2f388dad6833d5d11091013 100644
--- a/lib/manager/npm/extract/common.ts
+++ b/lib/manager/npm/extract/common.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line import/no-unresolved
 import { PackageJson } from 'type-fest';
 
 export interface NpmPackage extends PackageJson {
diff --git a/lib/manager/npm/post-update/index.ts b/lib/manager/npm/post-update/index.ts
index fe48b52a463ce0b512d46be691a97b29fdf45719..0f224e373bdb712c30141a231513cf8cfbe4847e 100644
--- a/lib/manager/npm/post-update/index.ts
+++ b/lib/manager/npm/post-update/index.ts
@@ -1,6 +1,7 @@
 import fs from 'fs-extra';
 import path from 'path';
 import upath from 'upath';
+// eslint-disable-next-line import/no-unresolved
 import { PackageJson } from 'type-fest';
 import { logger } from '../../../logger';
 import * as npm from './npm';
diff --git a/lib/platform/git/storage.ts b/lib/platform/git/storage.ts
index 0ada735638d6fb8241eb7e8132d31a3c3fda3b53..c6d29fef63de7211d65f3d38e8557446380b05e9 100644
--- a/lib/platform/git/storage.ts
+++ b/lib/platform/git/storage.ts
@@ -14,7 +14,6 @@ import {
 } from '../../constants/error-messages';
 
 declare module 'fs-extra' {
-  // eslint-disable-next-line import/prefer-default-export
   export function exists(pathLike: string): Promise<boolean>;
 }
 
diff --git a/lib/util/.eslintrc.js b/lib/util/.eslintrc.js
deleted file mode 100644
index 8bcc65cc06d65e68d5207c000f5167759c3b1dcd..0000000000000000000000000000000000000000
--- a/lib/util/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
-  rules: {
-    '@typescript-eslint/explicit-function-return-type': 2,
-  },
-};
diff --git a/lib/versioning/.eslintrc.js b/lib/versioning/.eslintrc.js
deleted file mode 100644
index 8bcc65cc06d65e68d5207c000f5167759c3b1dcd..0000000000000000000000000000000000000000
--- a/lib/versioning/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
-  rules: {
-    '@typescript-eslint/explicit-function-return-type': 2,
-  },
-};
diff --git a/package.json b/package.json
index 432996b1977064654d6ef2c0357e01b2d25069a5..c19b1a33232825d48ea9f2699f81a5a9844849e0 100644
--- a/package.json
+++ b/package.json
@@ -230,6 +230,7 @@
     "semantic-release": "15.14.0",
     "shelljs": "0.8.3",
     "tmp-promise": "2.0.2",
+    "type-fest": "0.10.0",
     "typescript": "3.7.5"
   },
   "resolutions": {
diff --git a/test/.eslintrc.js b/test/.eslintrc.js
deleted file mode 100644
index d7cc230f0a8d109050049d489125293f11b2a70d..0000000000000000000000000000000000000000
--- a/test/.eslintrc.js
+++ /dev/null
@@ -1,17 +0,0 @@
-module.exports = {
-  env: {
-    jest: true,
-  },
-  rules: {
-    'prefer-destructuring': 0,
-    'prefer-promise-reject-errors': 0,
-    'import/no-dynamic-require': 0,
-    'import/no-extraneous-dependencies': 0,
-    'import/no-named-as-default-member': 0,
-    'global-require': 0,
-
-    '@typescript-eslint/no-var-requires': 0,
-    '@typescript-eslint/no-object-literal-type-assertion': 0,
-    '@typescript-eslint/explicit-function-return-type': 0,
-  },
-};
diff --git a/test/newline-snapshot-serializer.ts b/test/newline-snapshot-serializer.ts
index 4a1c219f1884374c68fec21bc0a7c3d33f638686..0aa1c818f02892c44443069565b0b2f76a2be82b 100644
--- a/test/newline-snapshot-serializer.ts
+++ b/test/newline-snapshot-serializer.ts
@@ -1,9 +1,9 @@
 let prev: string;
 
-export function print(val: any) {
+export function print(val: any): string {
   return JSON.stringify(val);
 }
-export function test(val: any) {
+export function test(val: any): boolean {
   if (['prBody', 'prTitle'].some(str => str === prev)) {
     return typeof val === 'string' && val.includes('\n');
   }
diff --git a/test/renovate.spec.ts b/test/renovate.spec.ts
index 31379a8cf7cca634a38d125d159a91961e6ff54c..42d0271c90166327a0d9746ce8c70884bae4682a 100644
--- a/test/renovate.spec.ts
+++ b/test/renovate.spec.ts
@@ -1,7 +1,5 @@
 import * as renovateWorker from '../lib/workers/global';
 
-require('../lib/.eslintrc');
-
 Object.defineProperty(renovateWorker, 'start', { value: jest.fn() });
 
 describe('renovate', () => {
diff --git a/test/util/regex.spec.ts b/test/util/regex.spec.ts
index 3ad5a9ea356d631fb119ea92c9ff9f6b525e6962..18486582f9bce71ff41352d9e5a8c4b3eb0bae31 100644
--- a/test/util/regex.spec.ts
+++ b/test/util/regex.spec.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line import/no-extraneous-dependencies
 import RE2 from 're2';
 import { regEx } from '../../lib/util/regex';
 import { CONFIG_VALIDATION } from '../../lib/constants/error-messages';
diff --git a/tsconfig.dts.json b/tsconfig.dts.json
index 2366c742c512e048ac36025f5e3013c6142f2f95..0605e0d6229827f223ae216b4ff0bda4f0f5cf6b 100644
--- a/tsconfig.dts.json
+++ b/tsconfig.dts.json
@@ -3,8 +3,6 @@
   "compilerOptions": {
     "isolatedModules": false,
     "declaration": true,
-    "emitDeclarationOnly": true,
-    "allowJs": false,
-    "checkJs": false
+    "emitDeclarationOnly": true
   }
 }
diff --git a/tsconfig.json b/tsconfig.json
index d05ddae809a2441a3c27d2c4ce8ca9cff7000852..f1fd074f294059091400c59e928b90c8400fdda9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -5,8 +5,6 @@
     "strictNullChecks": false /* required for js files */,
     "outDir": "./dist",
     "target": "es2018",
-    "allowJs": true,
-    "checkJs": true,
     "module": "commonjs",
     "sourceMap": true,
     "allowSyntheticDefaultImports": true,
diff --git a/yarn.lock b/yarn.lock
index dde50f250ccdda3f540d8000b1d4b32aabf86f62..e1d1300d22eeb3a3a928a86b698d622519bb814d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6919,7 +6919,6 @@ npm@6.13.7, npm@^6.10.3:
     cmd-shim "^3.0.3"
     columnify "~1.5.4"
     config-chain "^1.1.12"
-    debuglog "*"
     detect-indent "~5.0.0"
     detect-newline "^2.1.0"
     dezalgo "~1.0.3"
@@ -6934,7 +6933,6 @@ npm@6.13.7, npm@^6.10.3:
     has-unicode "~2.0.1"
     hosted-git-info "^2.8.5"
     iferr "^1.0.2"
-    imurmurhash "*"
     infer-owner "^1.0.4"
     inflight "~1.0.6"
     inherits "^2.0.4"
@@ -6953,14 +6951,8 @@ npm@6.13.7, npm@^6.10.3:
     libnpx "^10.2.2"
     lock-verify "^2.1.0"
     lockfile "^1.0.4"
-    lodash._baseindexof "*"
     lodash._baseuniq "~4.6.0"
-    lodash._bindcallback "*"
-    lodash._cacheindexof "*"
-    lodash._createcache "*"
-    lodash._getnative "*"
     lodash.clonedeep "~4.5.0"
-    lodash.restparam "*"
     lodash.union "~4.6.0"
     lodash.uniq "~4.5.0"
     lodash.without "~4.4.0"
@@ -9449,6 +9441,11 @@ type-detect@4.0.8:
   resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
   integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
 
+type-fest@0.10.0:
+  version "0.10.0"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.10.0.tgz#7f06b2b9fbfc581068d1341ffabd0349ceafc642"
+  integrity sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==
+
 type-fest@^0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1"