diff --git a/lib/config/common.ts b/lib/config/common.ts
index 818b311a4227cee6b417ae4a9c660d861dfbc400..b057689f3b812291f6aa60c9eb2d400fb4caa0ae 100644
--- a/lib/config/common.ts
+++ b/lib/config/common.ts
@@ -37,6 +37,7 @@ export interface RenovateSharedConfig {
   platform?: string;
   postUpgradeTasks?: PostUpgradeTasks;
   prBodyColumns?: string[];
+  prBodyDefinitions?: Record<string, string>;
   prCreation?: 'immediate' | 'not-pending' | 'status-success' | 'approval';
   productLinks?: Record<string, string>;
   prPriority?: number;
diff --git a/lib/datasource/common.ts b/lib/datasource/common.ts
index 9b9037a8866ce00caaa0a925de5358003df304fe..d9c0ce47123fdd93783d2778160b9b0f365b90d4 100644
--- a/lib/datasource/common.ts
+++ b/lib/datasource/common.ts
@@ -36,7 +36,10 @@ export function isGetPkgReleasesConfig(
 }
 
 export interface Release {
+  canBeUnpublished?: boolean;
   changelogUrl?: string;
+  checksumUrl?: string;
+  downloadUrl?: string;
   gitRef?: string;
   isDeprecated?: boolean;
 
@@ -60,7 +63,7 @@ export interface ReleaseResult {
   pkgName?: string;
   releases: Release[];
   sourceUrl?: string;
-  tags?: string[];
+  tags?: Record<string, string>;
   versions?: any;
 }
 
diff --git a/lib/datasource/npm/get.ts b/lib/datasource/npm/get.ts
index 8510815ca3f935aa67b6e990b182f7e82413a230..f138f66a2ce3ba8d4c3f3c168e161256468ad4ae 100644
--- a/lib/datasource/npm/get.ts
+++ b/lib/datasource/npm/get.ts
@@ -15,7 +15,7 @@ import { getNpmrc } from './npmrc';
 
 const http = new Http(id);
 
-let memcache = {};
+let memcache: Record<string, string> = {};
 
 export function resetMemCache(): void {
   logger.debug('resetMemCache()');
@@ -38,7 +38,7 @@ export interface NpmDependency extends ReleaseResult {
   latestVersion: string;
   sourceUrl: string;
   versions: Record<string, any>;
-  'dist-tags': string[];
+  'dist-tags': Record<string, string>;
   'renovate-config': any;
   sourceDirectory?: string;
 }
diff --git a/lib/datasource/npm/releases.ts b/lib/datasource/npm/releases.ts
index 1af62cafbb5cb3046df55fd9ec289ff6f0df4317..ae4edbeaef2b8394aeab7d711a576e1acdb29357 100644
--- a/lib/datasource/npm/releases.ts
+++ b/lib/datasource/npm/releases.ts
@@ -9,7 +9,7 @@ export async function getReleases({
   if (npmrc) {
     setNpmrc(npmrc);
   }
-  const res: ReleaseResult = await getDependency(lookupName);
+  const res = await getDependency(lookupName);
   if (res) {
     res.tags = res['dist-tags'];
     delete res['dist-tags'];
diff --git a/lib/missing.d.ts b/lib/missing.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c5a5ccc8d5c1483b3ec6c4c8a416b5cf43f8bba8
--- /dev/null
+++ b/lib/missing.d.ts
@@ -0,0 +1,66 @@
+declare module 'conventional-commits-detector' {
+  function detector(commits: string[]): string;
+  export = detector;
+}
+
+declare module 'json-dup-key-validator' {
+  export function validate(
+    jsonString: string,
+    allowDuplicatedKeys?: boolean
+  ): string | undefined;
+
+  export function parse<T = unknown>(
+    jsonString: string,
+    allowDuplicatedKeys?: boolean
+  ): T;
+}
+
+declare module 'changelog-filename-regex' {
+  const re: RegExp;
+  export = re;
+}
+
+declare module 'linkify-markdown' {
+  export function linkify(
+    source: string,
+    options: Record<string, unknown>
+  ): string;
+}
+
+declare module 'get-installed-path' {
+  interface Options {
+    cwd?: string;
+    local?: boolean;
+    paths?: string[];
+  }
+  export function getInstalledPath(
+    arg: string,
+    opts?: Options
+  ): Promise<string>;
+}
+
+declare module '@snyk/ruby-semver/lib/ruby/gem-version' {
+  export function create(version: string): any;
+  export function parse(version: string): any;
+}
+
+declare module '@snyk/ruby-semver/lib/ruby/gem-requirement' {
+  export function parse(version: string): any;
+}
+
+declare module '@snyk/ruby-semver' {
+  export function diff(a: any, b: any): string;
+  export function eq(a: any, b: any): boolean;
+  export function gt(a: any, b: any): boolean;
+  export function gte(a: any, b: any): boolean;
+  export function lte(a: any, b: any): boolean;
+  export function major(version: any): number;
+  export function maxSatisfying(version: any[], range: string): string;
+  export function minSatisfying(version: any[], range: string): string;
+  export function minor(version: any): number;
+  export function patch(version: any): number;
+
+  export function prerelease(version: any): string[];
+  export function satisfies(version: any, range: string): boolean;
+  export function valid(version: any): boolean;
+}
diff --git a/lib/platform/azure/__snapshots__/index.spec.ts.snap b/lib/platform/azure/__snapshots__/index.spec.ts.snap
index d3ce8c6ad57481dd2543175f295599c8aceb5401..72bd61768f123f5d63d4beb909c89dd5348279b7 100644
--- a/lib/platform/azure/__snapshots__/index.spec.ts.snap
+++ b/lib/platform/azure/__snapshots__/index.spec.ts.snap
@@ -137,7 +137,7 @@ Object {
   "labels": Array [
     "renovate",
   ],
-  "pullRequestId": 1234,
+  "number": 1234,
 }
 `;
 
@@ -145,7 +145,7 @@ exports[`platform/azure getPr(prNo) should return a pr thats been modified 1`] =
 Object {
   "isModified": true,
   "labels": Array [],
-  "pullRequestId": 1234,
+  "number": 1234,
 }
 `;
 
diff --git a/lib/platform/azure/azure-helper.ts b/lib/platform/azure/azure-helper.ts
index d68dc1a2d516c0b0436f34e3a01bdcc753f75a4c..db438950f6a8a55f0c35016cc2c230de259f195e 100644
--- a/lib/platform/azure/azure-helper.ts
+++ b/lib/platform/azure/azure-helper.ts
@@ -4,7 +4,6 @@ import {
   GitPullRequestMergeStrategy,
   GitRef,
 } from 'azure-devops-node-api/interfaces/GitInterfaces';
-
 import { Options } from 'simple-git/promise';
 import {
   PR_STATE_CLOSED,
@@ -12,9 +11,10 @@ import {
   PR_STATE_OPEN,
 } from '../../constants/pull-requests';
 import { logger } from '../../logger';
+
 import { HostRule } from '../../types';
-import { Pr } from '../common';
 import * as azureApi from './azure-got-wrapper';
+import { AzurePr } from './types';
 
 const mergePolicyGuid = 'fa4e907d-c16b-4a4c-9dfa-4916e5d171ab'; // Magic GUID for merge strategy policy configurations
 
@@ -180,15 +180,15 @@ export function max4000Chars(str: string): string {
   return str;
 }
 
-export function getRenovatePRFormat(azurePr: GitPullRequest): Pr {
-  const pr: Pr = azurePr as any;
+export function getRenovatePRFormat(azurePr: GitPullRequest): AzurePr {
+  const pr: AzurePr = azurePr as any;
 
   pr.displayNumber = `Pull Request #${azurePr.pullRequestId}`;
   pr.number = azurePr.pullRequestId;
   pr.body = azurePr.description;
   pr.targetBranch = getBranchNameWithoutRefsheadsPrefix(azurePr.targetRefName);
   pr.branchName = pr.targetBranch;
-  pr.createdAt = pr.creationDate;
+  pr.createdAt = azurePr.creationDate?.toISOString();
 
   // status
   // export declare enum PullRequestStatus {
diff --git a/lib/platform/azure/index.spec.ts b/lib/platform/azure/index.spec.ts
index 084a6c511b78866604937490d66920309d6529c5..0762a6bbd95c29b7161337590c6aa69091467b70 100644
--- a/lib/platform/azure/index.spec.ts
+++ b/lib/platform/azure/index.spec.ts
@@ -505,7 +505,7 @@ describe('platform/azure', () => {
       azureHelper.getRenovatePRFormat.mockImplementation(
         () =>
           ({
-            pullRequestId: 1234,
+            number: 1234,
           } as any)
       );
       const pr = await azure.getPr(1234);
@@ -542,7 +542,7 @@ describe('platform/azure', () => {
       azureHelper.getRenovatePRFormat.mockImplementation(
         () =>
           ({
-            pullRequestId: 1234,
+            number: 1234,
             isModified: false,
           } as any)
       );
diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts
index 711fd0ba3d397192ec4ccba6c0d9123888633d60..9bb3700045da3632e2d8f108fa07ec4c5dff0b3d 100644
--- a/lib/platform/azure/index.ts
+++ b/lib/platform/azure/index.ts
@@ -2,7 +2,6 @@ import {
   GitPullRequest,
   GitPullRequestMergeStrategy,
 } from 'azure-devops-node-api/interfaces/GitInterfaces';
-
 import { RenovateConfig } from '../../config/common';
 import { REPOSITORY_DISABLED } from '../../constants/error-messages';
 import { PLATFORM_TYPE_AZURE } from '../../constants/platforms';
@@ -35,6 +34,7 @@ import GitStorage, { StatusResult } from '../git/storage';
 import { smartTruncate } from '../utils/pr-body';
 import * as azureApi from './azure-got-wrapper';
 import * as azureHelper from './azure-helper';
+import { AzurePr } from './types';
 
 interface Config {
   storage: GitStorage;
@@ -47,7 +47,8 @@ interface Config {
   repoId: string;
   project: string;
   azureWorkItemId: string;
-  prList: Pr[];
+  prList: AzurePr[];
+  fileList: null;
   repository: string;
 }
 
@@ -241,7 +242,7 @@ async function abandonPr(prNo: number): Promise<void> {
   );
 }
 
-export async function getPrList(): Promise<Pr[]> {
+export async function getPrList(): Promise<AzurePr[]> {
   logger.debug('getPrList()');
   if (!config.prList) {
     const azureApiGit = await azureApi.gitApi();
@@ -273,7 +274,7 @@ export async function getPr(pullRequestId: number): Promise<Pr | null> {
     return null;
   }
   const azurePr = (await getPrList()).find(
-    (item) => item.pullRequestId === pullRequestId
+    (item) => item.number === pullRequestId
   );
 
   if (!azurePr) {
@@ -345,7 +346,7 @@ export async function getBranchPr(branchName: string): Promise<Pr | null> {
     branchName,
     state: PR_STATE_OPEN,
   });
-  return existingPr ? getPr(existingPr.pullRequestId) : null;
+  return existingPr ? getPr(existingPr.number) : null;
 }
 
 export /* istanbul ignore next */ async function deleteBranch(
diff --git a/lib/platform/azure/types.ts b/lib/platform/azure/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..86b1282523876a6efc427d08503ec6b4aafa04f8
--- /dev/null
+++ b/lib/platform/azure/types.ts
@@ -0,0 +1,5 @@
+import { Pr } from '../common';
+
+export interface AzurePr extends Pr {
+  sourceRefName?: string;
+}
diff --git a/lib/platform/bitbucket-server/index.spec.ts b/lib/platform/bitbucket-server/index.spec.ts
index 9229a58a47f7a6d9af00bd2414d617b1f9778b51..2c90f2b2b127609e927d00b6aef8aa4213c1a72a 100644
--- a/lib/platform/bitbucket-server/index.spec.ts
+++ b/lib/platform/bitbucket-server/index.spec.ts
@@ -574,7 +574,7 @@ describe('platform/bitbucket-server', () => {
         it('posts PR', async () => {
           expect.assertions(3);
           await initRepo();
-          const { id } = await bitbucket.createPr({
+          const { number: id } = await bitbucket.createPr({
             branchName: 'branch',
             prTitle: 'title',
             prBody: 'body',
@@ -587,7 +587,7 @@ describe('platform/bitbucket-server', () => {
         it('posts PR default branch', async () => {
           expect.assertions(3);
           await initRepo();
-          const { id } = await bitbucket.createPr({
+          const { number: id } = await bitbucket.createPr({
             branchName: 'branch',
             prTitle: 'title',
             prBody: 'body',
diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts
index 3cdd5b269b077594f71a5b39d36f9b69af0e34f6..d5af7775967becffc93a1b4d13dada0110bbb713 100644
--- a/lib/platform/bitbucket-server/index.ts
+++ b/lib/platform/bitbucket-server/index.ts
@@ -1,6 +1,5 @@
 import url, { URLSearchParams } from 'url';
 import delay from 'delay';
-
 import { RenovateConfig } from '../../config/common';
 import {
   REPOSITORY_CHANGED,
@@ -34,7 +33,9 @@ import {
 import GitStorage, { StatusResult } from '../git/storage';
 import { smartTruncate } from '../utils/pr-body';
 import { api } from './bb-got-wrapper';
+import { BbbsRestPr, BbsConfig, BbsPr, BbsRestUserRef } from './types';
 import * as utils from './utils';
+import { PartialDeep } from 'type-fest';
 /*
  * Version: 5.3 (EOL Date: 15 Aug 2019)
  * See following docs for api information:
@@ -45,23 +46,6 @@ import * as utils from './utils';
  * https://confluence.atlassian.com/support/atlassian-support-end-of-life-policy-201851003.html#AtlassianSupportEndofLifePolicy-BitbucketServer
  */
 
-interface BbsConfig {
-  baseBranch: string;
-  bbUseDefaultReviewers: boolean;
-  defaultBranch: string;
-  mergeMethod: string;
-  owner: string;
-  prList: Pr[];
-  projectKey: string;
-  repository: string;
-  repositorySlug: string;
-  storage: GitStorage;
-
-  prVersions: Map<number, number>;
-
-  username: string;
-}
-
 let config: BbsConfig = {} as any;
 
 const defaults: any = {
@@ -293,7 +277,7 @@ export function isBranchStale(branchName: string): Promise<boolean> {
 export async function getPr(
   prNo: number,
   refreshCache?: boolean
-): Promise<Pr | null> {
+): Promise<BbsPr | null> {
   logger.debug(`getPr(${prNo})`);
   if (!prNo) {
     return null;
@@ -304,11 +288,11 @@ export async function getPr(
     { useCache: !refreshCache }
   );
 
-  const pr: any = {
+  const pr: BbsPr = {
     displayNumber: `Pull Request #${res.body.id}`,
     ...utils.prInfo(res.body),
     reviewers: res.body.reviewers.map(
-      (r: { user: { name: any } }) => r.user.name
+      (r: { user: { name: string } }) => r.user.name
     ),
     isModified: false,
   };
@@ -426,7 +410,7 @@ export async function findPr({
 export async function getBranchPr(
   branchName: string,
   refreshCache?: boolean
-): Promise<Pr | null> {
+): Promise<BbsPr | null> {
   logger.debug(`getBranchPr(${branchName})`);
   const existingPr = await findPr({
     branchName,
@@ -915,19 +899,19 @@ export async function createPr({
   const description = sanitize(rawDescription);
   logger.debug(`createPr(${branchName}, title=${title})`);
   const base = useDefaultBranch ? config.defaultBranch : config.baseBranch;
-  let reviewers = [];
+  let reviewers: BbsRestUserRef[] = [];
 
   /* istanbul ignore else */
   if (config.bbUseDefaultReviewers) {
     logger.debug(`fetching default reviewers`);
     const { id } = (
-      await api.get(
+      await api.get<{ id: number }>(
         `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}`
       )
     ).body;
 
     const defReviewers = (
-      await api.get(
+      await api.get<{ name: string }[]>(
         `./rest/default-reviewers/1.0/projects/${config.projectKey}/repos/${
           config.repositorySlug
         }/reviewers?sourceRefId=refs/heads/${escapeHash(
@@ -936,12 +920,12 @@ export async function createPr({
       )
     ).body;
 
-    reviewers = defReviewers.map((u: { name: string }) => ({
+    reviewers = defReviewers.map((u) => ({
       user: { name: u.name },
     }));
   }
 
-  const body = {
+  const body: PartialDeep<BbbsRestPr> = {
     title,
     description,
     fromRef: {
@@ -952,9 +936,9 @@ export async function createPr({
     },
     reviewers,
   };
-  let prInfoRes: GotResponse;
+  let prInfoRes: GotResponse<BbbsRestPr>;
   try {
-    prInfoRes = await api.post(
+    prInfoRes = await api.post<BbbsRestPr>(
       `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests`,
       { body }
     );
@@ -975,8 +959,7 @@ export async function createPr({
     throw err;
   }
 
-  const pr: Pr = {
-    id: prInfoRes.body.id,
+  const pr: BbsPr = {
     displayNumber: `Pull Request #${prInfoRes.body.id}`,
     isModified: false,
     ...utils.prInfo(prInfoRes.body),
diff --git a/lib/platform/bitbucket-server/types.ts b/lib/platform/bitbucket-server/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..aafd4b7dbac115fb7388a0e100c33cecd54770d6
--- /dev/null
+++ b/lib/platform/bitbucket-server/types.ts
@@ -0,0 +1,55 @@
+import { Pr } from '../common';
+import GitStorage from '../git/storage';
+
+export interface BbsConfig {
+  baseBranch: string;
+  bbUseDefaultReviewers: boolean;
+  defaultBranch: string;
+  fileList: any[];
+  mergeMethod: string;
+  owner: string;
+  prList: BbsPr[];
+  projectKey: string;
+  repository: string;
+  repositorySlug: string;
+  storage: GitStorage;
+
+  prVersions: Map<number, number>;
+
+  username: string;
+}
+
+export interface BbsPr extends Pr {
+  version?: number;
+}
+
+export enum BbsRestPrState {
+  Declined = 'DECLINED',
+  Open = 'OPEN',
+  Merged = 'MERGED',
+}
+
+export interface BbsRestBranchRef {
+  displayId: string;
+  id: string;
+}
+
+export interface BbsRestUser {
+  name: string;
+}
+
+export interface BbsRestUserRef {
+  user: BbsRestUser;
+}
+
+export interface BbbsRestPr {
+  createdDate: string;
+  description: string;
+  fromRef: BbsRestBranchRef;
+  id: number;
+  reviewers: BbsRestUserRef[];
+  state: BbsRestPrState;
+  title: string;
+  toRef: BbsRestBranchRef;
+  version?: number;
+}
diff --git a/lib/platform/bitbucket-server/utils.ts b/lib/platform/bitbucket-server/utils.ts
index 89c9d60f60ad22bafeb78cbe22cc4e3ed3bdd4cf..d9982c79c2ecb93ea540ce70f5ebc9d042b334eb 100644
--- a/lib/platform/bitbucket-server/utils.ts
+++ b/lib/platform/bitbucket-server/utils.ts
@@ -5,8 +5,8 @@ import {
   PR_STATE_MERGED,
   PR_STATE_OPEN,
 } from '../../constants/pull-requests';
-import { Pr } from '../common';
 import { api } from './bb-got-wrapper';
+import { BbbsRestPr, BbsPr } from './types';
 
 // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html#idp250
 const prStateMapping: any = {
@@ -15,7 +15,7 @@ const prStateMapping: any = {
   OPEN: PR_STATE_OPEN,
 };
 
-export function prInfo(pr: any): Pr {
+export function prInfo(pr: BbbsRestPr): BbsPr {
   return {
     version: pr.version,
     number: pr.id,
diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts
index 45f13da74f5bc1e9f59909e218471012d6895b38..39f1fa85a0803041a1edd2caefb322dcbb0f5425 100644
--- a/lib/platform/bitbucket/index.ts
+++ b/lib/platform/bitbucket/index.ts
@@ -729,7 +729,7 @@ export async function createPr({
 
   logger.debug({ repository: config.repository, title, base }, 'Creating PR');
 
-  let reviewers = [];
+  let reviewers: { uuid: { raw: string } }[] = [];
 
   if (config.bbUseDefaultReviewers) {
     const reviewersResponse = (
diff --git a/lib/platform/common.ts b/lib/platform/common.ts
index a561651e6ffb11129b61705f08a10334a481cd8d..6690e178b4b16c901b92714640aea818921ddf37 100644
--- a/lib/platform/common.ts
+++ b/lib/platform/common.ts
@@ -1,7 +1,12 @@
 import got from 'got';
 import Git from 'simple-git/promise';
 import { RenovateConfig } from '../config/common';
-import { BranchStatus } from '../types';
+import {
+  BranchStatus,
+  VulnerabilityAlert as _VulnerabilityAlert,
+} from '../types';
+
+export type VulnerabilityAlert = _VulnerabilityAlert;
 
 /**
  * File to commit to branch
@@ -93,15 +98,27 @@ export interface RepoParams {
 }
 
 /**
- * TODO: Proper typing
+ *
  */
-export type Pr = {
+export interface Pr {
+  body?: string;
   branchName: string;
-  title: string;
-  state: string;
+  canMerge?: boolean;
+  canMergeReason?: string;
+  createdAt?: string;
+  displayNumber?: string;
   isConflicted?: boolean;
   isModified?: boolean;
-} & Record<string, any>;
+  isStale?: boolean;
+  labels?: string[];
+  number?: number;
+  reviewers?: string[];
+  sha?: string;
+  sourceRepo?: string;
+  state: string;
+  targetBranch?: string;
+  title: string;
+}
 
 /**
  * TODO: Proper typing
@@ -154,10 +171,6 @@ export interface EnsureCommentRemovalConfig {
   topic?: string;
   content?: string;
 }
-/**
- * TODO: Proper typing
- */
-export type VulnerabilityAlert = any;
 
 export type EnsureIssueResult = 'updated' | 'created';
 
diff --git a/lib/platform/gitea/__snapshots__/index.spec.ts.snap b/lib/platform/gitea/__snapshots__/index.spec.ts.snap
index 3eb0dd25a0cda84efaaced7db72dec90314d5baf..c79019e9522ac5e3af413ad9fadfb25e013f7f4b 100644
--- a/lib/platform/gitea/__snapshots__/index.spec.ts.snap
+++ b/lib/platform/gitea/__snapshots__/index.spec.ts.snap
@@ -5,7 +5,6 @@ Object {
   "body": "pr-body",
   "branchName": "pr-branch",
   "canMerge": true,
-  "closedAt": "2017-12-28T12:17:48Z",
   "createdAt": "2014-04-01T05:14:20Z",
   "displayNumber": "Pull Request #42",
   "isConflicted": false,
@@ -25,7 +24,6 @@ Object {
   "body": "pr-body",
   "branchName": "pr-branch",
   "canMerge": true,
-  "closedAt": "2017-12-28T12:17:48Z",
   "createdAt": "2014-04-01T05:14:20Z",
   "displayNumber": "Pull Request #42",
   "isConflicted": false,
@@ -45,7 +43,6 @@ Object {
   "body": "some random pull request",
   "branchName": "some-head-branch",
   "canMerge": true,
-  "closedAt": null,
   "createdAt": "2015-03-22T20:36:16Z",
   "displayNumber": "Pull Request #1",
   "isConflicted": false,
@@ -65,7 +62,6 @@ Object {
   "body": "some random pull request",
   "branchName": "some-head-branch",
   "canMerge": true,
-  "closedAt": null,
   "createdAt": "2015-03-22T20:36:16Z",
   "displayNumber": "Pull Request #1",
   "isConflicted": false,
@@ -86,7 +82,6 @@ Array [
     "body": "some random pull request",
     "branchName": "some-head-branch",
     "canMerge": true,
-    "closedAt": null,
     "createdAt": "2015-03-22T20:36:16Z",
     "displayNumber": "Pull Request #1",
     "isConflicted": false,
@@ -103,7 +98,6 @@ Array [
     "body": "other random pull request",
     "branchName": "other-head-branch",
     "canMerge": true,
-    "closedAt": "2016-01-09T10:03:21Z",
     "createdAt": "2011-08-18T22:30:38Z",
     "displayNumber": "Pull Request #2",
     "isConflicted": false,
diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts
index e50378ddf0bb80551886fe28ed9e9deaf42fa585..ff00f8d0aae0f9d204d04eea7fa04a22a2632740 100644
--- a/lib/platform/gitea/index.ts
+++ b/lib/platform/gitea/index.ts
@@ -103,7 +103,6 @@ function toRenovatePR(data: helper.PR): Pr | null {
     targetBranch: data.base.ref,
     sourceRepo: data.head.repo.full_name,
     createdAt: data.created_at,
-    closedAt: data.closed_at,
     canMerge: data.mergeable,
     isConflicted: !data.mergeable,
     isStale: undefined,
diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts
index 9a1e7d5be4647732a393087bfef798f7ccd19316..636d2fe811ae4fb7f4a0e62bbb9cbc30c2d054a8 100644
--- a/lib/platform/github/index.ts
+++ b/lib/platform/github/index.ts
@@ -1,7 +1,6 @@
 import URL from 'url';
 import is from '@sindresorhus/is';
 import delay from 'delay';
-
 import { configFileNames } from '../../config/app-strings';
 import {
   PLATFORM_FAILURE,
@@ -39,6 +38,7 @@ import {
   FindPRConfig,
   Issue,
   PlatformConfig,
+  Pr,
   RepoConfig,
   RepoParams,
   VulnerabilityAlert,
@@ -47,60 +47,18 @@ import GitStorage, { StatusResult } from '../git/storage';
 import { smartTruncate } from '../utils/pr-body';
 import { api } from './gh-got-wrapper';
 import { getGraphqlNodes } from './gh-graphql-wrapper';
+import {
+  BranchProtection,
+  CombinedBranchStatus,
+  Comment,
+  GhBranchStatus,
+  GhPr,
+  LocalRepoConfig,
+  PrList,
+} from './types';
 
 const defaultConfigFile = configFileNames[0];
 
-interface Comment {
-  id: number;
-  body: string;
-}
-
-interface Pr {
-  displayNumber: string;
-  state: string;
-  title: string;
-  branchName: string;
-  number: number;
-  comments: Comment[];
-
-  createdAt: string;
-
-  sha: string;
-
-  sourceRepo: string;
-  isModified: boolean;
-}
-
-interface LocalRepoConfig {
-  repositoryName: string;
-  pushProtection: boolean;
-  prReviewsRequired: boolean;
-  repoForceRebase?: boolean;
-  storage: GitStorage;
-  parentRepo: string;
-  baseCommitSHA: string | null;
-  forkMode?: boolean;
-  forkToken?: string;
-  closedPrList: PrList | null;
-  openPrList: PrList | null;
-  prList: Pr[] | null;
-  issueList: any[] | null;
-  mergeMethod: string;
-  baseBranch: string;
-  defaultBranch: string;
-  enterpriseVersion: string;
-  gitPrivateKey?: string;
-  repositoryOwner: string;
-  repository: string | null;
-  localDir: string;
-  isGhe: boolean;
-  renovateUsername: string;
-  productLinks: any;
-}
-
-type BranchProtection = any;
-type PrList = Record<number, Pr>;
-
 let config: LocalRepoConfig = {} as any;
 
 const defaults = {
@@ -1063,20 +1021,6 @@ export async function getBranchPr(branchName: string): Promise<Pr | null> {
   return existingPr ? getPr(existingPr.number) : null;
 }
 
-// https://developer.github.com/v3/repos/statuses
-// https://developer.github.com/v3/checks/runs/
-type BranchState = 'failure' | 'pending' | 'success';
-
-interface GhBranchStatus {
-  context: string;
-  state: BranchState | 'error';
-}
-
-interface CombinedBranchStatus {
-  state: BranchState;
-  statuses: GhBranchStatus[];
-}
-
 async function getStatus(
   branchName: string,
   useCache = true
@@ -1104,7 +1048,7 @@ export async function getBranchStatus(
     logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`);
     return BranchStatus.red;
   }
-  let commitStatus;
+  let commitStatus: CombinedBranchStatus;
   try {
     commitStatus = await getStatus(branchName);
   } catch (err) /* istanbul ignore next */ {
@@ -1672,7 +1616,7 @@ export async function createPr({
   }
   logger.debug({ title, head, base }, 'Creating PR');
   const pr = (
-    await api.post<Pr>(
+    await api.post<GhPr>(
       `repos/${config.parentRepo || config.repository}/pulls`,
       options
     )
diff --git a/lib/platform/github/types.ts b/lib/platform/github/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a4f6ea91b6e091bc8fb89401ca0b63f2d7ff24ed
--- /dev/null
+++ b/lib/platform/github/types.ts
@@ -0,0 +1,56 @@
+import { Pr } from '../common';
+import GitStorage from '../git/storage';
+
+// https://developer.github.com/v3/repos/statuses
+// https://developer.github.com/v3/checks/runs/
+export type CombinedBranchState = 'failure' | 'pending' | 'success';
+export type BranchState = 'failure' | 'pending' | 'success' | 'error';
+
+export interface GhBranchStatus {
+  context: string;
+  state: BranchState;
+}
+
+export interface CombinedBranchStatus {
+  state: CombinedBranchState;
+  statuses: GhBranchStatus[];
+}
+
+export interface Comment {
+  id: number;
+  body: string;
+}
+
+export interface GhPr extends Pr {
+  comments: Comment[];
+}
+
+export interface LocalRepoConfig {
+  repositoryName: string;
+  pushProtection: boolean;
+  prReviewsRequired: boolean;
+  repoForceRebase?: boolean;
+  storage: GitStorage;
+  parentRepo: string;
+  baseCommitSHA: string | null;
+  forkMode?: boolean;
+  forkToken?: string;
+  closedPrList: PrList | null;
+  openPrList: PrList | null;
+  prList: GhPr[] | null;
+  issueList: any[] | null;
+  mergeMethod: string;
+  baseBranch: string;
+  defaultBranch: string;
+  enterpriseVersion: string;
+  gitPrivateKey?: string;
+  repositoryOwner: string;
+  repository: string | null;
+  localDir: string;
+  isGhe: boolean;
+  renovateUsername: string;
+  productLinks: any;
+}
+
+export type BranchProtection = any;
+export type PrList = Record<number, GhPr>;
diff --git a/lib/types/index.ts b/lib/types/index.ts
index fbc1cdb92d312aefe040d0f375a72ce36a2b4480..05321e3056e3bbe0afd07eb4d9a090ffcf451bef 100644
--- a/lib/types/index.ts
+++ b/lib/types/index.ts
@@ -2,3 +2,4 @@ export * from './host-rules';
 export * from './skip-reason';
 export * from './versioning';
 export * from './branch-status';
+export * from './vulnerability-alert';
diff --git a/lib/types/vulnerability-alert.ts b/lib/types/vulnerability-alert.ts
new file mode 100644
index 0000000000000000000000000000000000000000..be512c37aec39d0ef4196f469f742d94ed2be56e
--- /dev/null
+++ b/lib/types/vulnerability-alert.ts
@@ -0,0 +1,23 @@
+export interface VulnerabilityPackage {
+  ecosystem: 'MAVEN' | 'NPM' | 'NUGET' | 'PIP' | 'RUBYGEMS' | string;
+  name: string;
+}
+export interface SecurityVulnerability {
+  firstPatchedVersion?: { identifier: string };
+  package: VulnerabilityPackage;
+  vulnerableVersionRange: string;
+}
+export interface SecurityAdvisory {
+  description?: string;
+  identifiers?: { type: string; value: string }[];
+  references: { url: string }[];
+  severity: 'HIGH' | 'MODERATE' | string;
+}
+export interface VulnerabilityAlert {
+  dismissReason?: string | null;
+  securityAdvisory: SecurityAdvisory;
+  securityVulnerability: SecurityVulnerability;
+  vulnerableManifestFilename: string;
+  vulnerableManifestPath: string;
+  vulnerableRequirements?: string;
+}
diff --git a/lib/util/regex.ts b/lib/util/regex.ts
index 08aeebe210e12c2937dddb533f9bfa30a9806381..d1e7aa9559a9c56502372dc6711f81d41ea513f9 100644
--- a/lib/util/regex.ts
+++ b/lib/util/regex.ts
@@ -1,7 +1,7 @@
 import { CONFIG_VALIDATION } from '../constants/error-messages';
 import { logger } from '../logger';
 
-let RegEx;
+let RegEx: RegExpConstructor;
 
 try {
   // eslint-disable-next-line
diff --git a/lib/workers/branch/auto-replace.spec.ts b/lib/workers/branch/auto-replace.spec.ts
index d2c35d71b0046893463be80d7bfc1ff6d8bb19da..bd0ee1f1393f41981a7cce7f7152dad425679222 100644
--- a/lib/workers/branch/auto-replace.spec.ts
+++ b/lib/workers/branch/auto-replace.spec.ts
@@ -1,8 +1,8 @@
 import { readFileSync } from 'fs';
 import { resolve } from 'path';
 import { defaultConfig } from '../../../test/util';
-import { RenovateConfig } from '../../config';
 import { extractPackageFile } from '../../manager/html';
+import { BranchUpgradeConfig } from '../common';
 import { doAutoReplace } from './auto-replace';
 
 const sampleHtml = readFileSync(
@@ -14,8 +14,8 @@ jest.mock('../../util/fs');
 
 describe('workers/branch/auto-replace', () => {
   describe('doAutoReplace', () => {
-    let parentBranch;
-    let upgrade: RenovateConfig;
+    let parentBranch: string;
+    let upgrade: BranchUpgradeConfig;
     beforeEach(() => {
       upgrade = {
         ...JSON.parse(JSON.stringify(defaultConfig)),
diff --git a/lib/workers/branch/auto-replace.ts b/lib/workers/branch/auto-replace.ts
index ae075e7315824a8fba3977add59aa5c334a25c33..eb5259a26ad2ce5f8a83965b3ee132109834f093 100644
--- a/lib/workers/branch/auto-replace.ts
+++ b/lib/workers/branch/auto-replace.ts
@@ -1,13 +1,15 @@
 import { WORKER_FILE_UPDATE_FAILED } from '../../constants/error-messages';
 import { logger } from '../../logger';
 import { get } from '../../manager';
+import { PackageDependency } from '../../manager/common';
 import { writeLocalFile } from '../../util/fs';
 import { escapeRegExp, regEx } from '../../util/regex';
 import { matchAt, replaceAt } from '../../util/string';
 import { compile } from '../../util/template';
+import { BranchUpgradeConfig } from '../common';
 
 export async function confirmIfDepUpdated(
-  upgrade,
+  upgrade: BranchUpgradeConfig,
   newContent: string
 ): Promise<boolean> {
   const {
@@ -62,13 +64,13 @@ export async function confirmIfDepUpdated(
   return false;
 }
 
-function getDepsSignature(deps): string {
+function getDepsSignature(deps: PackageDependency[]): string {
   return deps.map((dep) => `${dep.depName}${dep.lookupName}`).join(',');
 }
 
 export async function checkBranchDepsMatchBaseDeps(
-  upgrade,
-  branchContent
+  upgrade: BranchUpgradeConfig,
+  branchContent: string
 ): Promise<boolean> {
   const { baseDeps, manager, packageFile } = upgrade;
   const extractPackageFile = get(manager, 'extractPackageFile');
@@ -86,7 +88,7 @@ export async function checkBranchDepsMatchBaseDeps(
 }
 
 export async function doAutoReplace(
-  upgrade,
+  upgrade: BranchUpgradeConfig,
   existingContent: string,
   parentBranch: string | null
 ): Promise<string | null> {
diff --git a/lib/workers/branch/get-updated.spec.ts b/lib/workers/branch/get-updated.spec.ts
index d3ab1cfdf80d8b9c1cfaf53bb63e9f66e4a85e19..74b6b6308c21d2051302a46b75ce6f388b0e3665 100644
--- a/lib/workers/branch/get-updated.spec.ts
+++ b/lib/workers/branch/get-updated.spec.ts
@@ -3,6 +3,7 @@ import * as datasourceGitSubmodules from '../../datasource/git-submodules';
 import * as _composer from '../../manager/composer';
 import * as _gitSubmodules from '../../manager/git-submodules';
 import * as _npm from '../../manager/npm';
+import { BranchConfig } from '../common';
 import * as _autoReplace from './auto-replace';
 import { getUpdatedPackageFiles } from './get-updated';
 
@@ -18,35 +19,35 @@ jest.mock('./auto-replace');
 
 describe('workers/branch/get-updated', () => {
   describe('getUpdatedPackageFiles()', () => {
-    let config;
+    let config: BranchConfig;
     beforeEach(() => {
       config = {
         ...defaultConfig,
         upgrades: [],
-      };
+      } as never;
       npm.updateDependency = jest.fn();
       platform.getFile.mockResolvedValueOnce('existing content');
     });
     it('handles autoreplace base updated', async () => {
-      config.upgrades.push({ manager: 'html' });
+      config.upgrades.push({ manager: 'html', branchName: undefined });
       autoReplace.doAutoReplace.mockResolvedValueOnce('updated-file');
       const res = await getUpdatedPackageFiles(config);
       expect(res).toMatchSnapshot();
     });
     it('handles autoreplace branch no update', async () => {
-      config.upgrades.push({ manager: 'html' });
+      config.upgrades.push({ manager: 'html', branchName: undefined });
       autoReplace.doAutoReplace.mockResolvedValueOnce('existing content');
       const res = await getUpdatedPackageFiles(config);
       expect(res).toMatchSnapshot();
     });
     it('handles autoreplace failure', async () => {
-      config.upgrades.push({ manager: 'html' });
+      config.upgrades.push({ manager: 'html', branchName: undefined });
       autoReplace.doAutoReplace.mockResolvedValueOnce(null);
       await expect(getUpdatedPackageFiles(config)).rejects.toThrow();
     });
     it('handles autoreplace branch needs update', async () => {
       config.parentBranch = 'some branch';
-      config.upgrades.push({ manager: 'html' });
+      config.upgrades.push({ manager: 'html', branchName: undefined });
       autoReplace.doAutoReplace.mockResolvedValueOnce(null);
       autoReplace.doAutoReplace.mockResolvedValueOnce('updated-file');
       const res = await getUpdatedPackageFiles(config);
@@ -60,14 +61,14 @@ describe('workers/branch/get-updated', () => {
       config.parentBranch = 'some-branch';
       config.upgrades.push({
         manager: 'npm',
-      });
+      } as never);
       await expect(getUpdatedPackageFiles(config)).rejects.toThrow();
     });
     it('handles content change', async () => {
       config.parentBranch = 'some-branch';
       config.upgrades.push({
         manager: 'npm',
-      });
+      } as never);
       npm.updateDependency.mockReturnValue('some new content');
       const res = await getUpdatedPackageFiles(config);
       expect(res).toMatchSnapshot();
@@ -76,6 +77,7 @@ describe('workers/branch/get-updated', () => {
       config.parentBranch = 'some-branch';
       config.upgrades.push({
         manager: 'composer',
+        branchName: undefined,
       });
       autoReplace.doAutoReplace.mockResolvedValueOnce('some new content');
       composer.updateArtifacts.mockResolvedValueOnce([
@@ -94,7 +96,7 @@ describe('workers/branch/get-updated', () => {
       config.upgrades.push({
         manager: 'composer',
         updateType: 'lockFileMaintenance',
-      });
+      } as never);
       composer.updateArtifacts.mockResolvedValueOnce([
         {
           file: {
@@ -111,7 +113,7 @@ describe('workers/branch/get-updated', () => {
       config.upgrades.push({
         manager: 'composer',
         updateType: 'lockFileMaintenance',
-      });
+      } as never);
       composer.updateArtifacts.mockResolvedValueOnce([
         {
           artifactError: {
@@ -127,6 +129,7 @@ describe('workers/branch/get-updated', () => {
       config.parentBranch = 'some-branch';
       config.upgrades.push({
         manager: 'composer',
+        branchName: undefined,
       });
       autoReplace.doAutoReplace.mockResolvedValueOnce('some new content');
       composer.updateArtifacts.mockResolvedValueOnce([
@@ -144,7 +147,7 @@ describe('workers/branch/get-updated', () => {
       config.upgrades.push({
         manager: 'git-submodules',
         datasource: datasourceGitSubmodules.id,
-      });
+      } as never);
       gitSubmodules.updateDependency.mockResolvedValueOnce('existing content');
       const res = await getUpdatedPackageFiles(config);
       expect(res).toMatchSnapshot();
diff --git a/lib/workers/branch/lock-files/index.spec.ts b/lib/workers/branch/lock-files/index.spec.ts
index 62d6314e066c4de63068b61c1a8f1bb166a676d1..5ee5f65fe4007a0bcb9f5eb7f516b78a37ed7161 100644
--- a/lib/workers/branch/lock-files/index.spec.ts
+++ b/lib/workers/branch/lock-files/index.spec.ts
@@ -1,6 +1,7 @@
 import _fs from 'fs-extra';
 import { mocked } from '../../../../test/util';
 import { getConfig } from '../../../config/defaults';
+import { PostUpdateConfig } from '../../../manager/common';
 import * as _lockFiles from '../../../manager/npm/post-update';
 import * as _lerna from '../../../manager/npm/post-update/lerna';
 import * as _npm from '../../../manager/npm/post-update/npm';
@@ -256,7 +257,7 @@ describe('manager/npm/post-update', () => {
   });
   */
   describe('writeUpdatedPackageFiles', () => {
-    let config;
+    let config: PostUpdateConfig;
     beforeEach(() => {
       config = {
         ...defaultConfig,
@@ -298,7 +299,7 @@ describe('manager/npm/post-update', () => {
     });
   });
   describe('getAdditionalFiles', () => {
-    let config;
+    let config: PostUpdateConfig;
     beforeEach(() => {
       config = {
         ...defaultConfig,
diff --git a/lib/workers/branch/lock-files/npm.spec.ts b/lib/workers/branch/lock-files/npm.spec.ts
index 97e7f952dac4e1de12bf9065dcec4fd7187956c6..d54be72105bde169f74615ec9669c27e93aa43e7 100644
--- a/lib/workers/branch/lock-files/npm.spec.ts
+++ b/lib/workers/branch/lock-files/npm.spec.ts
@@ -1,7 +1,7 @@
 import { exec as _exec } from 'child_process';
 import path from 'path';
 import _fs from 'fs-extra';
-import { getInstalledPath } from 'get-installed-path';
+import { getInstalledPath as _getInstalledPath } from 'get-installed-path';
 import { envMock, mockExecAll } from '../../../../test/execUtil';
 import { mocked } from '../../../../test/util';
 import * as npmHelper from '../../../manager/npm/post-update/npm';
@@ -13,6 +13,7 @@ jest.mock('child_process');
 jest.mock('../../../util/exec/env');
 jest.mock('get-installed-path');
 
+const getInstalledPath: jest.Mock<string> = _getInstalledPath as never;
 getInstalledPath.mockImplementation(() => null);
 const exec: jest.Mock<typeof _exec> = _exec as any;
 const env = mocked(_env);
diff --git a/lib/workers/branch/lock-files/pnpm.spec.ts b/lib/workers/branch/lock-files/pnpm.spec.ts
index 98a0084b40bdc560621a6281254ebb167847d7d6..2069352e4c251f297a7727b88103e232f25d9180 100644
--- a/lib/workers/branch/lock-files/pnpm.spec.ts
+++ b/lib/workers/branch/lock-files/pnpm.spec.ts
@@ -1,8 +1,9 @@
 import { exec as _exec } from 'child_process';
 import _fs from 'fs-extra';
-import { getInstalledPath } from 'get-installed-path';
+import { getInstalledPath as _getInstalledPath } from 'get-installed-path';
 import { envMock, mockExecAll } from '../../../../test/execUtil';
 import { mocked } from '../../../../test/util';
+import { PostUpdateConfig } from '../../../manager/common';
 import * as _pnpmHelper from '../../../manager/npm/post-update/pnpm';
 import { BinarySource } from '../../../util/exec/common';
 import * as _env from '../../../util/exec/env';
@@ -12,6 +13,7 @@ jest.mock('child_process');
 jest.mock('../../../util/exec/env');
 jest.mock('get-installed-path');
 
+const getInstalledPath: jest.Mock<string> = _getInstalledPath as never;
 getInstalledPath.mockImplementation(() => null);
 
 const exec: jest.Mock<typeof _exec> = _exec as any;
@@ -20,7 +22,7 @@ const fs = mocked(_fs);
 const pnpmHelper = mocked(_pnpmHelper);
 
 describe('generateLockFile', () => {
-  let config;
+  let config: PostUpdateConfig;
   beforeEach(() => {
     config = { cacheDir: 'some-cache-dir' };
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
diff --git a/lib/workers/branch/lock-files/yarn.spec.ts b/lib/workers/branch/lock-files/yarn.spec.ts
index 6dcbf1afb35eb9cef990b2b0c3f81d7eca1d63d3..cac97c2475f7dc702f00c4a0816db9db928fd2bd 100644
--- a/lib/workers/branch/lock-files/yarn.spec.ts
+++ b/lib/workers/branch/lock-files/yarn.spec.ts
@@ -1,6 +1,6 @@
 import { exec as _exec } from 'child_process';
 import _fs from 'fs-extra';
-import { getInstalledPath } from 'get-installed-path';
+import { getInstalledPath as _getInstalledPath } from 'get-installed-path';
 import { ExecSnapshots, envMock, mockExecAll } from '../../../../test/execUtil';
 import { getName, mocked } from '../../../../test/util';
 import * as _yarnHelper from '../../../manager/npm/post-update/yarn';
@@ -12,6 +12,7 @@ jest.mock('child_process');
 jest.mock('../../../util/exec/env');
 jest.mock('get-installed-path');
 
+const getInstalledPath: jest.Mock<string> = _getInstalledPath as never;
 getInstalledPath.mockImplementation(() => null);
 
 const exec: jest.Mock<typeof _exec> = _exec as any;
diff --git a/lib/workers/branch/schedule.spec.ts b/lib/workers/branch/schedule.spec.ts
index fcc6f51536368b985d1d22b6daf24a4ae1d801a9..1a7655a71edff7d8c0ceddc5af706bbd356841da 100644
--- a/lib/workers/branch/schedule.spec.ts
+++ b/lib/workers/branch/schedule.spec.ts
@@ -1,4 +1,5 @@
 import mockDate from 'mockdate';
+import { RenovateConfig } from '../../config';
 import * as schedule from './schedule';
 
 describe('workers/branch/schedule', () => {
@@ -98,7 +99,7 @@ describe('workers/branch/schedule', () => {
     });
   });
   describe('isScheduledNow(config)', () => {
-    let config;
+    let config: RenovateConfig;
     beforeEach(() => {
       mockDate.set('2017-06-30T10:50:00.000'); // Locally 2017-06-30 10:50am
       jest.resetAllMocks();
@@ -109,7 +110,7 @@ describe('workers/branch/schedule', () => {
       expect(res).toBe(true);
     });
     it('returns true if at any time', () => {
-      config.schedule = 'at any time';
+      config.schedule = 'at any time' as never;
       const res = schedule.isScheduledNow(config);
       expect(res).toBe(true);
     });
@@ -140,7 +141,7 @@ describe('workers/branch/schedule', () => {
       expect(res).toBe(false);
     });
     it('massages string', () => {
-      config.schedule = 'before 4:00am';
+      config.schedule = 'before 4:00am' as never;
       const res = schedule.isScheduledNow(config);
       expect(res).toBe(false);
     });
diff --git a/lib/workers/branch/schedule.ts b/lib/workers/branch/schedule.ts
index a81981d79fd4bf42c75b953c9e0bb1f221cb2de5..56f4a5f4e5e6c5ade0ad6f5d05a4d5a5be818c92 100644
--- a/lib/workers/branch/schedule.ts
+++ b/lib/workers/branch/schedule.ts
@@ -1,9 +1,10 @@
 import is from '@sindresorhus/is';
 import later from 'later';
 import moment from 'moment-timezone';
+import { RenovateConfig } from '../../config';
 import { logger } from '../../logger';
 
-const scheduleMappings = {
+const scheduleMappings: Record<string, string> = {
   'every month': 'before 3am on the first day of the month',
   monthly: 'before 3am on the first day of the month',
 };
@@ -65,14 +66,14 @@ export function hasValidSchedule(
   return [true, ''];
 }
 
-export function isScheduledNow(config): boolean {
+export function isScheduledNow(config: RenovateConfig): boolean {
   let configSchedule = config.schedule;
   logger.debug(`Checking schedule(${configSchedule}, ${config.timezone})`);
   if (
     !configSchedule ||
     configSchedule.length === 0 ||
     configSchedule[0] === '' ||
-    configSchedule === 'at any time' ||
+    configSchedule === ('at any time' as never) ||
     configSchedule[0] === 'at any time'
   ) {
     logger.debug('No schedule defined');
diff --git a/lib/workers/common.ts b/lib/workers/common.ts
index 53eec7aefacd2159745bf7b9c6caab3e5a2a9c5b..d1c95cbbad90159d38e9de35187b8df05bb22dac 100644
--- a/lib/workers/common.ts
+++ b/lib/workers/common.ts
@@ -21,6 +21,8 @@ export interface BranchUpgradeConfig
     Partial<LookupUpdate>,
     RenovateSharedConfig {
   artifactErrors?: ArtifactError[];
+  autoReplaceStringTemplate?: string;
+  baseDeps?: PackageDependency[];
   branchName: string;
   commitBody?: string;
   commitMessage?: string;
@@ -31,6 +33,7 @@ export interface BranchUpgradeConfig
   currentVersion?: string;
   endpoint?: string;
   excludeCommitPaths?: string[];
+  githubName?: string;
   group?: GroupConfig;
 
   groupName?: string;
@@ -47,6 +50,7 @@ export interface BranchUpgradeConfig
   prTitle?: string;
   releases?: Release[];
   releaseTimestamp?: string;
+  repoName?: string;
 
   sourceDirectory?: string;
 
@@ -87,11 +91,13 @@ export interface BranchConfig
   extends BranchUpgradeConfig,
     RenovateAdminConfig,
     PlatformPrOptions {
+  automergeComment?: string;
   automergeType?: string;
   baseBranch?: string;
   canBeUnpublished?: boolean;
   errors?: ValidationMessage[];
   hasTypes?: boolean;
+  masterIssueChecks?: Record<string, string>;
   releaseTimestamp?: string;
 
   res?: ProcessBranchResult;
diff --git a/lib/workers/global/autodiscover.spec.ts b/lib/workers/global/autodiscover.spec.ts
index 16a9fae2c103628758f72d4fb53462439a50e497..4023c2c4d4b821a211c2d6c8b1589f59bfa88baf 100644
--- a/lib/workers/global/autodiscover.spec.ts
+++ b/lib/workers/global/autodiscover.spec.ts
@@ -1,3 +1,4 @@
+import { RenovateConfig } from '../../config';
 import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms';
 import * as platform from '../../platform';
 import * as _ghApi from '../../platform/github';
@@ -12,7 +13,7 @@ const hostRules = _hostRules;
 const ghApi: jest.Mocked<typeof _ghApi> = _ghApi as never;
 
 describe('lib/workers/global/autodiscover', () => {
-  let config;
+  let config: RenovateConfig;
   beforeEach(async () => {
     jest.resetAllMocks();
     config = {};
diff --git a/lib/workers/pr/changelog/release-notes.spec.ts b/lib/workers/pr/changelog/release-notes.spec.ts
index 5c5846d9178ff8e5328c7d5ece1636429e66a9d8..33f2bf50977cb03b85e708da7b909d6f1187bc2a 100644
--- a/lib/workers/pr/changelog/release-notes.spec.ts
+++ b/lib/workers/pr/changelog/release-notes.spec.ts
@@ -1,5 +1,6 @@
 import fs from 'fs-extra';
 import got from '../../../util/got';
+import { ChangeLogNotes } from './common';
 import {
   addReleaseNotes,
   getReleaseNotes,
@@ -186,8 +187,8 @@ describe('workers/pr/release-notes', () => {
       expect(res).toMatchSnapshot();
     });
     describe('ReleaseNotes Correctness', () => {
-      let versionOneNotes;
-      let versionTwoNotes;
+      let versionOneNotes: ChangeLogNotes;
+      let versionTwoNotes: ChangeLogNotes;
       it('parses yargs 15.3.0', async () => {
         ghGot
           .mockResolvedValueOnce({ body: contentsResponse })
diff --git a/lib/workers/pr/index.spec.ts b/lib/workers/pr/index.spec.ts
index 73e59842e3053f63fa525625ed796ad4e97bba5c..ef07b1d19eb291b8e74a2337fe92b97dbc95867c 100644
--- a/lib/workers/pr/index.spec.ts
+++ b/lib/workers/pr/index.spec.ts
@@ -1,9 +1,9 @@
-import { mocked } from '../../../test/util';
+import { mocked, partial } from '../../../test/util';
 import { getConfig } from '../../config/defaults';
 import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms';
 import { Pr, platform as _platform } from '../../platform';
 import { BranchStatus } from '../../types';
-import { PrResult } from '../common';
+import { BranchConfig, PrResult } from '../common';
 import * as _changelogHelper from './changelog';
 import { getChangeLogJSON } from './changelog';
 import * as prWorker from '.';
@@ -53,18 +53,15 @@ function setupChangelogMock() {
 
 describe('workers/pr', () => {
   describe('checkAutoMerge(pr, config)', () => {
-    let config;
-    let pr;
+    let config: BranchConfig;
+    let pr: Pr;
     beforeEach(() => {
-      config = {
+      config = partial<BranchConfig>({
         ...defaultConfig,
-      };
-      pr = {
-        head: {
-          ref: 'somebranch',
-        },
+      });
+      pr = partial<Pr>({
         canMerge: true,
-      };
+      });
     });
     afterEach(() => {
       jest.clearAllMocks();
@@ -117,7 +114,7 @@ describe('workers/pr', () => {
     });
   });
   describe('ensurePr', () => {
-    let config;
+    let config: BranchConfig;
     // TODO fix type
     const existingPr: Pr = {
       displayNumber: 'Existing PR',
@@ -128,9 +125,9 @@ describe('workers/pr', () => {
     } as never;
     beforeEach(() => {
       setupChangelogMock();
-      config = {
+      config = partial<BranchConfig>({
         ...defaultConfig,
-      };
+      });
       config.branchName = 'renovate/dummy-1.x';
       config.prTitle = 'Update dependency dummy to v1.1.0';
       config.depType = 'devDependencies';
@@ -184,7 +181,7 @@ describe('workers/pr', () => {
       config.logJSON = await getChangeLogJSON(config);
       config.prCreation = 'status-success';
       config.automerge = true;
-      config.schedule = 'before 5am';
+      config.schedule = ['before 5am'];
       const { prResult, pr } = await prWorker.ensurePr(config);
       expect(prResult).toEqual(PrResult.Created);
       expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
@@ -215,7 +212,7 @@ describe('workers/pr', () => {
           updateType: 'lockFileMaintenance',
           prBodyNotes: ['{{#if foo}}'],
         },
-      ]);
+      ] as never);
       config.updateType = 'lockFileMaintenance';
       config.recreateClosed = true;
       config.rebaseWhen = 'never';
@@ -232,7 +229,7 @@ describe('workers/pr', () => {
       config.prCreation = 'status-success';
       config.isPin = true;
       config.updateType = 'pin';
-      config.schedule = 'before 5am';
+      config.schedule = ['before 5am'];
       config.timezone = 'some timezone';
       config.rebaseWhen = 'behind-base-branch';
       config.logJSON = await getChangeLogJSON(config);
@@ -374,7 +371,7 @@ describe('workers/pr', () => {
       platform.getBranchPr.mockResolvedValueOnce(existingPr);
       config.semanticCommitScope = null;
       config.automerge = true;
-      config.schedule = 'before 5am';
+      config.schedule = ['before 5am'];
       config.logJSON = await getChangeLogJSON(config);
       const { prResult, pr } = await prWorker.ensurePr(config);
       expect(prResult).toEqual(PrResult.NotUpdated);
@@ -389,7 +386,7 @@ describe('workers/pr', () => {
       platform.getBranchPr.mockResolvedValueOnce(modifiedPr);
       config.semanticCommitScope = null;
       config.automerge = true;
-      config.schedule = 'before 5am';
+      config.schedule = ['before 5am'];
       config.logJSON = await getChangeLogJSON(config);
       const { prResult, pr } = await prWorker.ensurePr(config);
       expect(prResult).toEqual(PrResult.NotUpdated);
@@ -399,7 +396,7 @@ describe('workers/pr', () => {
     it('should return modified existing PR', async () => {
       config.newValue = '1.2.0';
       config.automerge = true;
-      config.schedule = 'before 5am';
+      config.schedule = ['before 5am'];
       config.logJSON = await getChangeLogJSON(config);
       platform.getBranchPr.mockResolvedValueOnce(existingPr);
       const { prResult, pr } = await prWorker.ensurePr(config);
diff --git a/lib/workers/pr/index.ts b/lib/workers/pr/index.ts
index c3259564ec5ed4da84a50639cc4774c7c130e99f..495eb7b0a6c2f3fc903cf781d0132f3002e637a1 100644
--- a/lib/workers/pr/index.ts
+++ b/lib/workers/pr/index.ts
@@ -21,7 +21,11 @@ function noLeadingAtSymbol(input: string): string {
   return input.length && input.startsWith('@') ? input.slice(1) : input;
 }
 
-export async function addAssigneesReviewers(config, pr: Pr): Promise<void> {
+// TODO: fix types
+export async function addAssigneesReviewers(
+  config: any,
+  pr: Pr
+): Promise<void> {
   if (config.assignees.length > 0) {
     try {
       let assignees = config.assignees.map(noLeadingAtSymbol);
@@ -180,8 +184,8 @@ export async function ensurePr(
     logger.debug('Branch status success');
   }
 
-  const processedUpgrades = [];
-  const commitRepos = [];
+  const processedUpgrades: string[] = [];
+  const commitRepos: string[] = [];
 
   // Get changelog and then generate template strings
   for (const upgrade of upgrades) {
@@ -234,7 +238,7 @@ export async function ensurePr(
   Object.assign(config, upgrades[0]);
   config.hasReleaseNotes = config.upgrades.some((upg) => upg.hasReleaseNotes);
 
-  const releaseNoteRepos = [];
+  const releaseNoteRepos: string[] = [];
   for (const upgrade of config.upgrades) {
     if (upgrade.hasReleaseNotes) {
       if (releaseNoteRepos.includes(upgrade.sourceUrl)) {
@@ -347,7 +351,7 @@ export async function ensurePr(
         if (err.body.errors && err.body.errors.length) {
           if (
             err.body.errors.some(
-              (error) =>
+              (error: { message?: string }) =>
                 error.message &&
                 error.message.startsWith('A pull request already exists')
             )
@@ -422,7 +426,10 @@ export async function ensurePr(
   return { prResult: PrResult.Error };
 }
 
-export async function checkAutoMerge(pr: Pr, config): Promise<boolean> {
+export async function checkAutoMerge(
+  pr: Pr,
+  config: BranchConfig
+): Promise<boolean> {
   logger.trace({ config }, 'checkAutoMerge');
   const {
     branchName,
diff --git a/lib/workers/repository/extract/file-match.ts b/lib/workers/repository/extract/file-match.ts
index 04e6ee64f0726a54d0f396e80b5732caf51dd095..921e3f8f539856a2fee1d9d8d7ccd11b94b4272f 100644
--- a/lib/workers/repository/extract/file-match.ts
+++ b/lib/workers/repository/extract/file-match.ts
@@ -55,7 +55,7 @@ export async function getMatchingFiles(
   const allFiles = await getFileList();
   const fileList = getFilteredFileList(config, allFiles);
   const { fileMatch, manager } = config;
-  let matchedFiles = [];
+  let matchedFiles: string[] = [];
   for (const match of fileMatch) {
     logger.debug(`Using file match: ${match} for manager ${manager}`);
     const re = new RegExp(match);
diff --git a/lib/workers/repository/extract/manager-files.ts b/lib/workers/repository/extract/manager-files.ts
index c8a37e9b383b4a69ebcd9955e7de1b32bd968696..c3e8880ffccc0c8ca74f20bdb13482d5493d8b53 100644
--- a/lib/workers/repository/extract/manager-files.ts
+++ b/lib/workers/repository/extract/manager-files.ts
@@ -44,7 +44,7 @@ export async function getManagerPackageFiles(
     }
     return allPackageFiles;
   }
-  const packageFiles = [];
+  const packageFiles: PackageFile[] = [];
   for (const packageFile of fileList) {
     const content = await readLocalFile(packageFile, 'utf8');
     if (content) {
diff --git a/lib/workers/repository/finalise/validate.ts b/lib/workers/repository/finalise/validate.ts
index 1a0a245824baa378c3c58a760e7c5cfb532d5e8a..3d42669b9ccd1babd0c0594990e203dcc36eca23 100644
--- a/lib/workers/repository/finalise/validate.ts
+++ b/lib/workers/repository/finalise/validate.ts
@@ -31,7 +31,7 @@ export async function validatePrs(config: RenovateConfig): Promise<void> {
   logger.debug('branchPrefix: ' + config.branchPrefix);
   const renovatePrs = await getRenovatePrs(config.branchPrefix);
   logger.debug({ renovatePrs }, `Found ${renovatePrs.length} Renovate PRs`);
-  let validations = [];
+  let validations: { file: string; message: string }[] = [];
   for (const pr of renovatePrs) {
     try {
       const renovateFiles = await getRenovateFiles(pr.number);
diff --git a/lib/workers/repository/init/apis.ts b/lib/workers/repository/init/apis.ts
index 0e84164b8d1f893463f20dc920a8993126402602..526825540084a7317b864d8b55e79244c31f1df4 100644
--- a/lib/workers/repository/init/apis.ts
+++ b/lib/workers/repository/init/apis.ts
@@ -1,6 +1,6 @@
 import { RenovateConfig } from '../../../config';
 import * as npmApi from '../../../datasource/npm';
-import { RepoConfig, platform } from '../../../platform';
+import { RepoConfig, RepoParams, platform } from '../../../platform';
 
 // TODO: fix types
 export type WorkerPlatformConfig = RepoConfig &
@@ -8,7 +8,9 @@ export type WorkerPlatformConfig = RepoConfig &
   Record<string, any>;
 
 // TODO: fix types
-async function getPlatformConfig(config): Promise<WorkerPlatformConfig> {
+async function getPlatformConfig(
+  config: RepoParams
+): Promise<WorkerPlatformConfig> {
   const platformConfig = await platform.initRepo(config);
   return {
     ...config,
@@ -21,7 +23,7 @@ export async function initApis(
   input: RenovateConfig
 ): Promise<WorkerPlatformConfig> {
   let config: WorkerPlatformConfig = { ...input } as never;
-  config = await getPlatformConfig(config);
+  config = await getPlatformConfig(config as never);
   npmApi.resetMemCache();
   npmApi.setNpmrc(config.npmrc);
   delete config.gitPrivateKey;
diff --git a/lib/workers/repository/init/base.ts b/lib/workers/repository/init/base.ts
index 79d41699cf53ad5be02a88628a22b4dbe85daf28..099efbe2ec8380fdce9e103be3489cf46ea61e8f 100644
--- a/lib/workers/repository/init/base.ts
+++ b/lib/workers/repository/init/base.ts
@@ -1,4 +1,4 @@
-import { RenovateConfig } from '../../../config';
+import { RenovateConfig, ValidationMessage } from '../../../config';
 import { logger } from '../../../logger';
 import { platform } from '../../../platform';
 
@@ -7,7 +7,7 @@ export async function checkBaseBranch(
 ): Promise<RenovateConfig> {
   logger.debug('checkBaseBranch()');
   logger.debug(`config.repoIsOnboarded=${config.repoIsOnboarded}`);
-  let error = [];
+  let error: ValidationMessage[] = [];
   let baseBranchSha: string;
   // istanbul ignore else
   if (config.baseBranch) {
diff --git a/lib/workers/repository/init/vulnerability.spec.ts b/lib/workers/repository/init/vulnerability.spec.ts
index e7a4a39c30ebeb2f6c10f6fe2183f480da10680c..9388b81a6d877e5ccc2d1d565fce38cd9792167d 100644
--- a/lib/workers/repository/init/vulnerability.spec.ts
+++ b/lib/workers/repository/init/vulnerability.spec.ts
@@ -1,5 +1,11 @@
-import { RenovateConfig, defaultConfig, platform } from '../../../../test/util';
+import {
+  RenovateConfig,
+  defaultConfig,
+  partial,
+  platform,
+} from '../../../../test/util';
 import { REPOSITORY_NO_VULNERABILITY } from '../../../constants/error-messages';
+import { VulnerabilityAlert } from '../../../types';
 import { detectVulnerabilityAlerts } from './vulnerability';
 
 let config: RenovateConfig;
@@ -33,7 +39,7 @@ describe('workers/repository/init/vulnerability', () => {
     it('returns alerts', async () => {
       delete config.vulnerabilityAlerts.enabled;
       platform.getVulnerabilityAlerts.mockResolvedValue([
-        {},
+        partial<VulnerabilityAlert>({}),
         {
           dismissReason: null,
           vulnerableManifestFilename: 'package-lock.json',
diff --git a/lib/workers/repository/init/vulnerability.ts b/lib/workers/repository/init/vulnerability.ts
index 07856b97c798f2692eb4ef5a3745ab7cac62a7bd..8a9c4a7481c6061d05108f0de7db159d4f4e24e6 100644
--- a/lib/workers/repository/init/vulnerability.ts
+++ b/lib/workers/repository/init/vulnerability.ts
@@ -7,6 +7,7 @@ import * as datasourcePypi from '../../../datasource/pypi';
 import * as datasourceRubygems from '../../../datasource/rubygems';
 import { logger } from '../../../logger';
 import { platform } from '../../../platform';
+import { SecurityAdvisory } from '../../../types';
 import * as allVersioning from '../../../versioning';
 import * as mavenVersioning from '../../../versioning/maven';
 import * as npmVersioning from '../../../versioning/npm';
@@ -14,6 +15,19 @@ import * as pep440Versioning from '../../../versioning/pep440';
 import * as rubyVersioning from '../../../versioning/ruby';
 import * as semverVersioning from '../../../versioning/semver';
 
+type CombinedAlert = Record<
+  string,
+  Record<
+    string,
+    {
+      advisories: SecurityAdvisory[];
+      fileNames: string[];
+      firstPatchedVersion?: string;
+      vulnerableRequirements?: string;
+    }
+  >
+>;
+
 export async function detectVulnerabilityAlerts(
   input: RenovateConfig
 ): Promise<RenovateConfig> {
@@ -33,7 +47,7 @@ export async function detectVulnerabilityAlerts(
     return input;
   }
   const config = { ...input };
-  const combinedAlerts = {};
+  const combinedAlerts: CombinedAlert = {};
   for (const alert of alerts) {
     try {
       if (alert.dismissReason) {
@@ -46,7 +60,7 @@ export async function detectVulnerabilityAlerts(
         );
         continue; // eslint-disable-line no-continue
       }
-      const datasourceMapping = {
+      const datasourceMapping: Record<string, string> = {
         MAVEN: datasourceMaven.id,
         NPM: datasourceNpm.id,
         NUGET: datasourceNuget.id,
@@ -74,7 +88,7 @@ export async function detectVulnerabilityAlerts(
       }
       const firstPatchedVersion =
         alert.securityVulnerability.firstPatchedVersion.identifier;
-      const versionings = {
+      const versionings: Record<string, string> = {
         maven: mavenVersioning.id,
         npm: npmVersioning.id,
         nuget: semverVersioning.id,
@@ -113,7 +127,7 @@ export async function detectVulnerabilityAlerts(
   const alertPackageRules = [];
   for (const [datasource, dependencies] of Object.entries(combinedAlerts)) {
     for (const [depName, val] of Object.entries(dependencies)) {
-      let prBodyNotes = [];
+      let prBodyNotes: string[] = [];
       try {
         prBodyNotes = ['### GitHub Vulnerability Alerts'].concat(
           val.advisories.map((advisory) => {
diff --git a/lib/workers/repository/master-issue.spec.ts b/lib/workers/repository/master-issue.spec.ts
index 423774928780c0d545b8c6fddee522a0cfd4516b..00c39bbcfdd1cd3f27edc5a5af394db5996b1696 100644
--- a/lib/workers/repository/master-issue.spec.ts
+++ b/lib/workers/repository/master-issue.spec.ts
@@ -3,7 +3,7 @@ import { mock } from 'jest-mock-extended';
 import { RenovateConfig, getConfig, platform } from '../../../test/util';
 import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms';
 import { PR_STATE_NOT_OPEN } from '../../constants/pull-requests';
-import { Pr } from '../../platform';
+import { Platform, Pr } from '../../platform';
 import { BranchConfig, BranchUpgradeConfig } from '../common';
 import * as masterIssue from './master-issue';
 
@@ -21,7 +21,7 @@ beforeEach(() => {
 async function dryRun(
   branches: BranchConfig[],
   // eslint-disable-next-line no-shadow
-  platform,
+  platform: jest.Mocked<Platform>,
   ensureIssueClosingCalls = 0,
   ensureIssueCalls = 0,
   getBranchPrCalls = 0,
diff --git a/lib/workers/repository/onboarding/pr/config-description.spec.ts b/lib/workers/repository/onboarding/pr/config-description.spec.ts
index 2a18b25611be58f62104cfa19a828719a148e1a8..fc5dd3f78a24509fa00bcb4d0907a0572b654093 100644
--- a/lib/workers/repository/onboarding/pr/config-description.spec.ts
+++ b/lib/workers/repository/onboarding/pr/config-description.spec.ts
@@ -1,5 +1,5 @@
 import { RenovateConfig, getConfig } from '../../../../../test/util';
-
+import { PackageFile } from '../../../../manager/common';
 import { getConfigDesc } from './config-description';
 
 describe('workers/repository/onboarding/pr/config-description', () => {
@@ -15,7 +15,7 @@ describe('workers/repository/onboarding/pr/config-description', () => {
       expect(res).toMatchSnapshot();
     });
     it('returns a full list', () => {
-      const packageFiles = {
+      const packageFiles: Record<string, PackageFile[]> = {
         npm: [],
         dockerfile: [],
       };
diff --git a/lib/workers/repository/onboarding/pr/errors-warnings.spec.ts b/lib/workers/repository/onboarding/pr/errors-warnings.spec.ts
index e517222f612f30c0508ada4b9a17d02859c37e9f..85c0b439b35c631e44d1c0b5b93b9437c9ee0bb6 100644
--- a/lib/workers/repository/onboarding/pr/errors-warnings.spec.ts
+++ b/lib/workers/repository/onboarding/pr/errors-warnings.spec.ts
@@ -1,5 +1,5 @@
 import { RenovateConfig, getConfig } from '../../../../../test/util';
-
+import { PackageFile } from '../../../../manager/common';
 import { getDepWarnings, getErrors, getWarnings } from './errors-warnings';
 
 describe('workers/repository/onboarding/pr/errors-warnings', () => {
@@ -25,7 +25,7 @@ describe('workers/repository/onboarding/pr/errors-warnings', () => {
       jest.resetAllMocks();
     });
     it('returns warning text', () => {
-      const packageFiles = {
+      const packageFiles: Record<string, PackageFile[]> = {
         npm: [
           {
             packageFile: 'package.json',
diff --git a/lib/workers/repository/onboarding/pr/errors-warnings.ts b/lib/workers/repository/onboarding/pr/errors-warnings.ts
index a53eee19cb193704fe3de6dd1b866d93e7fc32c6..ce84a8d5fcf4d353a3f08f2ec96ce1864ffe6f2f 100644
--- a/lib/workers/repository/onboarding/pr/errors-warnings.ts
+++ b/lib/workers/repository/onboarding/pr/errors-warnings.ts
@@ -35,8 +35,8 @@ export function getDepWarnings(
 ): string {
   let warningText = '';
   try {
-    const warnings = [];
-    const warningFiles = [];
+    const warnings: string[] = [];
+    const warningFiles: string[] = [];
     for (const files of Object.values(packageFiles || {})) {
       for (const file of files || []) {
         if (file.deps) {
diff --git a/lib/workers/repository/onboarding/pr/index.spec.ts b/lib/workers/repository/onboarding/pr/index.spec.ts
index 17b1a40cb982c7b9a37cc53a2c9f05e86550acf5..d0e87c264cc875a914c8cc37306dd4b795283e56 100644
--- a/lib/workers/repository/onboarding/pr/index.spec.ts
+++ b/lib/workers/repository/onboarding/pr/index.spec.ts
@@ -1,15 +1,18 @@
-import { RenovateConfig, defaultConfig } from '../../../../../test/util';
+import {
+  RenovateConfig,
+  defaultConfig,
+  partial,
+  platform,
+} from '../../../../../test/util';
+import { PackageFile } from '../../../../manager/common';
+import { Pr } from '../../../../platform';
 import { BranchConfig } from '../../../common';
-
-const { platform } = require('../../../../platform');
-const { ensureOnboardingPr } = require('.');
-
-/** @type any */
+import { ensureOnboardingPr } from '.';
 
 describe('workers/repository/onboarding/pr', () => {
   describe('ensureOnboardingPr()', () => {
     let config: RenovateConfig;
-    let packageFiles;
+    let packageFiles: Record<string, PackageFile[]>;
     let branches: BranchConfig[];
     beforeEach(() => {
       jest.resetAllMocks();
@@ -19,10 +22,10 @@ describe('workers/repository/onboarding/pr', () => {
         warnings: [],
         description: [],
       };
-      packageFiles = { npm: [{ packageFile: 'package.json' }] };
+      packageFiles = { npm: [{ packageFile: 'package.json', deps: [] }] };
       branches = [];
       platform.getPrBody = jest.fn((input) => input);
-      platform.createPr.mockReturnValue({});
+      platform.createPr.mockResolvedValueOnce(partial<Pr>({}));
     });
     let createPrBody: string;
     it('returns if onboarded', async () => {
@@ -35,34 +38,40 @@ describe('workers/repository/onboarding/pr', () => {
       createPrBody = platform.createPr.mock.calls[0][0].prBody;
     });
     it('returns if PR does not need updating', async () => {
-      platform.getBranchPr.mockReturnValue({
-        title: 'Configure Renovate',
-        body: createPrBody,
-        isModified: false,
-      });
+      platform.getBranchPr.mockResolvedValue(
+        partial<Pr>({
+          title: 'Configure Renovate',
+          body: createPrBody,
+          isModified: false,
+        })
+      );
       await ensureOnboardingPr(config, packageFiles, branches);
       expect(platform.createPr).toHaveBeenCalledTimes(0);
       expect(platform.updatePr).toHaveBeenCalledTimes(0);
     });
     it('updates PR', async () => {
       config.baseBranch = 'some-branch';
-      platform.getBranchPr.mockReturnValue({
-        title: 'Configure Renovate',
-        body: createPrBody,
-        isConflicted: true,
-        isModified: true,
-      });
+      platform.getBranchPr.mockResolvedValueOnce(
+        partial<Pr>({
+          title: 'Configure Renovate',
+          body: createPrBody,
+          isConflicted: true,
+          isModified: true,
+        })
+      );
       await ensureOnboardingPr(config, {}, branches);
       expect(platform.createPr).toHaveBeenCalledTimes(0);
       expect(platform.updatePr).toHaveBeenCalledTimes(1);
     });
     it('updates PR', async () => {
       config.baseBranch = 'some-branch';
-      platform.getBranchPr.mockReturnValue({
-        title: 'Configure Renovate',
-        body: createPrBody,
-        isModified: true,
-      });
+      platform.getBranchPr.mockResolvedValueOnce(
+        partial<Pr>({
+          title: 'Configure Renovate',
+          body: createPrBody,
+          isModified: true,
+        })
+      );
       await ensureOnboardingPr(config, {}, branches);
       expect(platform.createPr).toHaveBeenCalledTimes(0);
       expect(platform.updatePr).toHaveBeenCalledTimes(1);
diff --git a/lib/workers/repository/onboarding/pr/index.ts b/lib/workers/repository/onboarding/pr/index.ts
index 4501ce7532d565a0693ee8c841eea54e9c6d011c..15d59ce4b7f65944ccba753107f1aeee04fd64bc 100644
--- a/lib/workers/repository/onboarding/pr/index.ts
+++ b/lib/workers/repository/onboarding/pr/index.ts
@@ -50,7 +50,7 @@ If you need any further assistance then you can also [request help here](${confi
   );
   let prBody = prTemplate;
   if (packageFiles && Object.entries(packageFiles).length) {
-    let files = [];
+    let files: string[] = [];
     for (const [manager, managerFiles] of Object.entries(packageFiles)) {
       files = files.concat(
         managerFiles.map((file) => ` * \`${file.packageFile}\` (${manager})`)
@@ -115,7 +115,7 @@ If you need any further assistance then you can also [request help here](${confi
     return;
   }
   logger.debug('Creating onboarding PR');
-  const labels = [];
+  const labels: string[] = [];
   const useDefaultBranch = true;
   try {
     // istanbul ignore if
diff --git a/lib/workers/repository/onboarding/pr/pr-list.spec.ts b/lib/workers/repository/onboarding/pr/pr-list.spec.ts
index c001bb6f504a0a272497931115bff2aa6ef84049..ceb33f0caf13197d3a9884d313ae67017c000b81 100644
--- a/lib/workers/repository/onboarding/pr/pr-list.spec.ts
+++ b/lib/workers/repository/onboarding/pr/pr-list.spec.ts
@@ -1,4 +1,5 @@
 import { RenovateConfig, getConfig } from '../../../../../test/util';
+import { BranchConfig } from '../../../common';
 import { getPrList } from './pr-list';
 
 describe('workers/repository/onboarding/pr/pr-list', () => {
@@ -9,7 +10,7 @@ describe('workers/repository/onboarding/pr/pr-list', () => {
       config = getConfig();
     });
     it('handles emptyu', () => {
-      const branches = [];
+      const branches: BranchConfig[] = [];
       const res = getPrList(config, branches);
       expect(res).toMatchSnapshot();
     });
diff --git a/lib/workers/repository/onboarding/pr/pr-list.ts b/lib/workers/repository/onboarding/pr/pr-list.ts
index 80960b4073bea123befbfeba3e7d57bd1c2b8c0d..0b9463fce5643c0c88f08a8096b9ccdce46deccf 100644
--- a/lib/workers/repository/onboarding/pr/pr-list.ts
+++ b/lib/workers/repository/onboarding/pr/pr-list.ts
@@ -29,7 +29,7 @@ export function getPrList(
     prDesc += branch.baseBranch
       ? `  - Merge into: \`${branch.baseBranch}\`\n`
       : '';
-    const seen = [];
+    const seen: string[] = [];
     for (const upgrade of branch.upgrades) {
       let text = '';
       if (upgrade.updateType === 'lockFileMaintenance') {
diff --git a/lib/workers/repository/process/deprecated.spec.ts b/lib/workers/repository/process/deprecated.spec.ts
index 5946616ae879bf5d10deb50fffc92fea9d90ba23..7d9c79a28f3e21284a065387cce9208c0f0425aa 100644
--- a/lib/workers/repository/process/deprecated.spec.ts
+++ b/lib/workers/repository/process/deprecated.spec.ts
@@ -1,4 +1,4 @@
-import { platform } from '../../../../test/util';
+import { RenovateConfig, platform } from '../../../../test/util';
 import { raiseDeprecationWarnings } from './deprecated';
 
 describe('workers/repository/process/deprecated', () => {
@@ -8,14 +8,14 @@ describe('workers/repository/process/deprecated', () => {
       await raiseDeprecationWarnings(config, {});
     });
     it('returns if disabled', async () => {
-      const config = {
+      const config: RenovateConfig = {
         repoIsOnboarded: true,
         suppressNotifications: ['deprecationWarningIssues'],
       };
       await raiseDeprecationWarnings(config, {});
     });
     it('raises deprecation warnings', async () => {
-      const config = {
+      const config: RenovateConfig = {
         repoIsOnboarded: true,
         suppressNotifications: [],
       };
diff --git a/lib/workers/repository/process/fetch.spec.ts b/lib/workers/repository/process/fetch.spec.ts
index 2b5310430be7842366a589341e78561de0402d05..d71d727ca6d07d0821a9c6ab611b3642834269cb 100644
--- a/lib/workers/repository/process/fetch.spec.ts
+++ b/lib/workers/repository/process/fetch.spec.ts
@@ -1,7 +1,7 @@
 import { RenovateConfig, getConfig, mocked } from '../../../../test/util';
 import * as datasourceMaven from '../../../datasource/maven';
 import * as datasourceNpm from '../../../datasource/npm';
-import { ManagerApi } from '../../../manager/common';
+import { ManagerApi, PackageFile } from '../../../manager/common';
 import * as _npm from '../../../manager/npm';
 import { fetchUpdates } from './fetch';
 import * as lookup from './lookup';
@@ -19,7 +19,7 @@ describe('workers/repository/process/fetch', () => {
       config = getConfig();
     });
     it('handles empty deps', async () => {
-      const packageFiles = {
+      const packageFiles: Record<string, PackageFile[]> = {
         npm: [{ packageFile: 'package.json', deps: [] }],
       };
       await fetchUpdates(config, packageFiles);
@@ -33,7 +33,7 @@ describe('workers/repository/process/fetch', () => {
           enabled: false,
         },
       ];
-      const packageFiles: any = {
+      const packageFiles: Record<string, PackageFile[]> = {
         npm: [
           {
             packageFile: 'package.json',
@@ -41,7 +41,7 @@ describe('workers/repository/process/fetch', () => {
               { depName: 'abcd' },
               { depName: 'zzzz' },
               { depName: 'foo' },
-              { depName: 'skipped', skipReason: 'some-reason' },
+              { depName: 'skipped', skipReason: 'some-reason' as never },
             ],
             internalPackages: ['zzzz'],
           },
diff --git a/lib/workers/repository/process/limits.spec.ts b/lib/workers/repository/process/limits.spec.ts
index 2ba44289ec8f366e523d50e9bfd483d00558d2a3..f698036f60f4e3d007228c864bc688f92006f8e4 100644
--- a/lib/workers/repository/process/limits.spec.ts
+++ b/lib/workers/repository/process/limits.spec.ts
@@ -15,7 +15,7 @@ describe('workers/repository/process/limits', () => {
       config.prHourlyLimit = 2;
       platform.getPrList.mockResolvedValueOnce([
         {
-          created_at: moment().format(),
+          createdAt: moment().toISOString(),
           branchName: null,
           title: null,
           state: null,
diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts
index cf17b9e7c0417a261cb044c3d8af4dcaadb54fda..ecaf7062ed24eb717c1da31ab3fb1d2ad9dd09ff 100644
--- a/lib/workers/repository/process/lookup/index.spec.ts
+++ b/lib/workers/repository/process/lookup/index.spec.ts
@@ -1,5 +1,5 @@
 import nock from 'nock';
-import { getConfig, mocked } from '../../../../../test/util';
+import { getConfig, mocked, partial } from '../../../../../test/util';
 import qJson from '../../../../config/npm/__fixtures__/01.json';
 import helmetJson from '../../../../config/npm/__fixtures__/02.json';
 import coffeelintJson from '../../../../config/npm/__fixtures__/coffeelint.json';
@@ -30,11 +30,12 @@ qJson.latestVersion = '1.4.1';
 const docker = mocked(datasourceDocker);
 const gitSubmodules = mocked(datasourceGitSubmodules);
 
-let config;
+let config: lookup.LookupUpdateConfig;
 
 describe('workers/repository/process/lookup', () => {
   beforeEach(() => {
-    config = getConfig();
+    // TODO: fix types
+    config = partial<lookup.LookupUpdateConfig>(getConfig());
     config.manager = 'npm';
     config.versioning = npmVersioning.id;
     config.rangeStrategy = 'replace';
diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts
index 2086b5f368d054585f9b324d0882028a264465b9..4a97ca511cded8c426fd6c4859b621c4aa3d3d9c 100644
--- a/lib/workers/repository/process/lookup/index.ts
+++ b/lib/workers/repository/process/lookup/index.ts
@@ -279,7 +279,7 @@ export async function lookupUpdates(
     if (vulnerabilityAlert) {
       filteredVersions = filteredVersions.slice(0, 1);
     }
-    const buckets = {};
+    const buckets: Record<string, LookupUpdate> = {};
     for (const toVersion of filteredVersions) {
       const update: LookupUpdate = { fromVersion, toVersion } as any;
       try {
@@ -327,14 +327,17 @@ export async function lookupUpdates(
         version.equals(release.version, toVersion)
       );
       // TODO: think more about whether to just Object.assign this
-      const releaseFields = [
-        'releaseTimestamp',
-        'canBeUnpublished',
-        'newDigest',
-      ];
+      const releaseFields: (keyof Pick<
+        Release,
+        | 'releaseTimestamp'
+        | 'canBeUnpublished'
+        | 'downloadUrl'
+        | 'checksumUrl'
+        | 'newDigest'
+      >)[] = ['releaseTimestamp', 'canBeUnpublished', 'newDigest'];
       releaseFields.forEach((field) => {
         if (updateRelease[field] !== undefined) {
-          update[field] = updateRelease[field];
+          update[field] = updateRelease[field] as never;
         }
       });
 
diff --git a/lib/workers/repository/updates/branchify.ts b/lib/workers/repository/updates/branchify.ts
index 102333c64be3108fb7cb13b6db90d9f6279d8252..6113b1b0a6af8373327d21188f79a0daa2e8fe1a 100644
--- a/lib/workers/repository/updates/branchify.ts
+++ b/lib/workers/repository/updates/branchify.ts
@@ -163,7 +163,7 @@ export async function branchifyUpgrades(
   try {
     // Here we check if there are updates from the same source repo
     // that are not grouped into the same branch
-    const branchUpdates = {};
+    const branchUpdates: Record<string, Record<string, string>> = {};
     for (const branch of branches) {
       const { sourceUrl, branchName, depName, toVersion } = branch;
       if (sourceUrl && toVersion) {
diff --git a/lib/workers/repository/updates/generate.spec.ts b/lib/workers/repository/updates/generate.spec.ts
index f1c20c273edd9bc628703a34d51c0ccffa200681..fad0842c56f41cc29b522632f11654db7ddb19be 100644
--- a/lib/workers/repository/updates/generate.spec.ts
+++ b/lib/workers/repository/updates/generate.spec.ts
@@ -370,7 +370,7 @@ describe('workers/repository/updates/generate', () => {
       expect(res.prTitle).toMatchSnapshot();
     });
     it('handles @types specially', () => {
-      const branch = [
+      const branch: BranchUpgradeConfig[] = [
         {
           commitBodyTable: true,
           datasource: datasourceNpm.id,
@@ -401,7 +401,7 @@ describe('workers/repository/updates/generate', () => {
       expect(res.groupName).toBeUndefined();
     });
     it('handles @types specially (reversed)', () => {
-      const branch = [
+      const branch: BranchUpgradeConfig[] = [
         {
           depName: 'some-dep',
           groupName: null,
@@ -424,7 +424,7 @@ describe('workers/repository/updates/generate', () => {
       expect(generateBranchConfig(branch)).toMatchSnapshot();
     });
     it('handles upgrades', () => {
-      const branch = [
+      const branch: BranchUpgradeConfig[] = [
         {
           depName: 'some-dep',
           branchName: 'some-branch',
diff --git a/lib/workers/repository/updates/generate.ts b/lib/workers/repository/updates/generate.ts
index 69d323122a01e1a75efbe4dac96c3590068cc7ad..c37f56c146b69f9b1ca78bf8c797c50aca54d994 100644
--- a/lib/workers/repository/updates/generate.ts
+++ b/lib/workers/repository/updates/generate.ts
@@ -69,9 +69,9 @@ export function generateBranchConfig(
   const hasGroupName = branchUpgrades[0].groupName !== null;
   logger.trace(`hasGroupName: ${hasGroupName}`);
   // Use group settings only if multiple upgrades or lazy grouping is disabled
-  const depNames = [];
-  const newValue = [];
-  const toVersions = [];
+  const depNames: string[] = [];
+  const newValue: string[] = [];
+  const toVersions: string[] = [];
   branchUpgrades.forEach((upg) => {
     if (!depNames.includes(upg.depName)) {
       depNames.push(upg.depName);
diff --git a/package.json b/package.json
index e60be20aeb0efcd78c5ef9f1006b62f076f3f335..5aab8921fa6d1c38aefa1cb5ce1533af571fd27e 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
     "test-schema": "babel-node --extensions \".ts,.js\" -- test/json-schema.ts",
     "test": "run-s lint test-schema type-check jest",
     "tsc": "tsc",
-    "type-check": "run-s generate:* \"tsc --noEmit\"",
+    "type-check": "run-s generate:* \"tsc --noEmit {@}\"",
     "verify": "node --experimental-modules tools/verify.mjs"
   },
   "repository": {
@@ -205,6 +205,7 @@
     "@types/lodash": "4.14.150",
     "@types/luxon": "1.22.0",
     "@types/markdown-it": "10.0.1",
+    "@types/markdown-table": "2.0.0",
     "@types/moment-timezone": "0.5.13",
     "@types/nock": "10.0.3",
     "@types/node": "11.15.12",
diff --git a/test/execUtil.ts b/test/execUtil.ts
index d1ea80aac1cdea5d3745264f0f4a02fc5c015d99..babd4063a1f7c9462a4875a5a3cc3fb4fe523010 100644
--- a/test/execUtil.ts
+++ b/test/execUtil.ts
@@ -35,7 +35,7 @@ export function mockExecAll(
   execFn: jest.Mock<typeof _exec>,
   execResult: ExecResult = defaultExecResult
 ): ExecSnapshots {
-  const snapshots = [];
+  const snapshots: ExecSnapshots = [];
   execFn.mockImplementation((cmd, options, callback) => {
     snapshots.push(execSnapshot(cmd, options));
     if (execResult instanceof Error) {
@@ -51,7 +51,7 @@ export function mockExecSequence(
   execFn: jest.Mock<typeof _exec>,
   execResults: ExecResult[]
 ): ExecSnapshots {
-  const snapshots = [];
+  const snapshots: ExecSnapshots = [];
   execResults.forEach((execResult) => {
     execFn.mockImplementationOnce((cmd, options, callback) => {
       snapshots.push(execSnapshot(cmd, options));
diff --git a/tsconfig.app.json b/tsconfig.app.json
index 07124cae000fe0a264c63f492b538f073aef9626..4377e2261e05f5214022a2dbdb23283ca75af14a 100644
--- a/tsconfig.app.json
+++ b/tsconfig.app.json
@@ -2,6 +2,7 @@
   "extends": "./tsconfig",
   "compilerOptions": {
     "resolveJsonModule": false,
+    "noImplicitAny": false,
     "isolatedModules": true,
     "sourceMap": true,
     "inlineSources": true,
diff --git a/yarn.lock b/yarn.lock
index a2ee17007a178f274055cf8a18b39fbf5d11b4ea..67ffb9f32b3f96f9a2d3233977d604aa25891c31 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1545,6 +1545,11 @@
   resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9"
   integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==
 
+"@types/markdown-table@2.0.0":
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/@types/markdown-table/-/markdown-table-2.0.0.tgz#d2a3458c61ee71c8ee2b40b76c199b85b8dbd70c"
+  integrity sha512-fVZN/DRjZvjuk+lo7ovlI/ZycS51gpYU5vw5EcFeqkcX6lucQ+UWgEOH2O4KJHkSck4DHAY7D7CkVLD0wzc5qw==
+
 "@types/minimatch@*", "@types/minimatch@^3.0.3":
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"