diff --git a/lib/datasource/cargo/index.js b/lib/datasource/cargo/index.ts
similarity index 83%
rename from lib/datasource/cargo/index.js
rename to lib/datasource/cargo/index.ts
index ccda70e2e93640101db77ba3767740d9f266ae75..9896a4f22a0f2332fb59b52c3a28a9147b04d8cc 100644
--- a/lib/datasource/cargo/index.js
+++ b/lib/datasource/cargo/index.ts
@@ -1,25 +1,27 @@
-const { logger } = require('../../logger');
-const got = require('../../util/got');
+import { logger } from '../../logger';
+import got from '../../util/got';
+import { PkgReleaseConfig, ReleaseResult, Release } from '../common';
 
-module.exports = {
-  getPkgReleases,
-};
-
-async function getPkgReleases({ lookupName }) {
+export async function getPkgReleases({
+  lookupName,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   if (!lookupName) {
     return null;
   }
 
   const cacheNamespace = 'datasource-cargo';
   const cacheKey = lookupName;
-  const cachedResult = await renovateCache.get(cacheNamespace, cacheKey);
+  const cachedResult = await renovateCache.get<ReleaseResult>(
+    cacheNamespace,
+    cacheKey
+  );
   // istanbul ignore if
   if (cachedResult) {
     return cachedResult;
   }
 
   const len = lookupName.length;
-  let path;
+  let path: string;
   // Ignored because there is no way to test this without hitting up GitHub API
   /* istanbul ignore next */
   if (len === 1) {
@@ -72,11 +74,11 @@ async function getPkgReleases({ lookupName }) {
       );
       return null;
     }
-    const result = {
+    const result: ReleaseResult = {
       releases: [],
     };
-    result.releases = res.map(version => {
-      const release = {
+    result.releases = res.map((version: { vers: string; yanked: boolean }) => {
+      const release: Release = {
         version: version.vers,
       };
       if (version.yanked) {
diff --git a/lib/datasource/common.ts b/lib/datasource/common.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b6373f0c5a7d827432480fe9964519d8b3e41370
--- /dev/null
+++ b/lib/datasource/common.ts
@@ -0,0 +1,51 @@
+export interface Config {
+  datasource?: string;
+  depName?: string;
+  lookupName?: string;
+  registryUrls?: string[];
+}
+export interface PkgReleaseConfig extends Config {
+  compatibility?: Record<string, string>;
+  depType?: string;
+  lookupType?: string;
+  npmrc?: string;
+  versionScheme?: string;
+}
+
+export type DigestConfig = Config;
+
+export interface Release {
+  changelogUrl?: string;
+  gitref?: string;
+  isDeprecated?: boolean;
+
+  releaseDate?: string;
+  releaseTimestamp?: any;
+  version: string;
+}
+
+export interface ReleaseResult {
+  changelogUrl?: string;
+  dependencyUrl?: string;
+  deprecationMessage?: string;
+  display?: string;
+  dockerRegistry?: string;
+  dockerRepository?: string;
+  group?: string;
+  homepage?: string;
+  name?: string;
+  pkgName?: string;
+  releases: Release[];
+  sourceUrl?: string;
+  tags?: string[];
+  versions?: any;
+}
+
+// TODO: Proper typing
+export type Preset = any;
+
+export interface Datasource {
+  getDigest?(config: DigestConfig, newValue?: string): Promise<string>;
+  getPreset?(packageName: string, presetName?: string): Promise<Preset>;
+  getPkgReleases(config: PkgReleaseConfig): Promise<ReleaseResult>;
+}
diff --git a/lib/datasource/dart/index.js b/lib/datasource/dart/index.ts
similarity index 71%
rename from lib/datasource/dart/index.js
rename to lib/datasource/dart/index.ts
index e8d9f4df4a7978dc1426dbeb1b2625865c244bda..432892ddf648af83eec74a7becfa5cbc667dc5db 100644
--- a/lib/datasource/dart/index.js
+++ b/lib/datasource/dart/index.ts
@@ -1,11 +1,24 @@
-const got = require('../../util/got');
-const { logger } = require('../../logger');
+import got from '../../util/got';
+import { logger } from '../../logger';
+import { ReleaseResult, PkgReleaseConfig } from '../common';
 
-async function getPkgReleases({ lookupName }) {
-  /** @type any */
-  let result = null;
+export async function getPkgReleases({
+  lookupName,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
+  let result: ReleaseResult = null;
   const pkgUrl = `https://pub.dartlang.org/api/packages/${lookupName}`;
-  let raw = null;
+  interface DartResult {
+    versions?: {
+      version: string;
+    }[];
+    latest?: {
+      pubspec?: { homepage?: string; repository?: string };
+    };
+  }
+
+  let raw: {
+    body: DartResult;
+  } = null;
   try {
     raw = await got(pkgUrl, {
       json: true,
@@ -53,7 +66,3 @@ async function getPkgReleases({ lookupName }) {
 
   return result;
 }
-
-module.exports = {
-  getPkgReleases,
-};
diff --git a/lib/datasource/docker/index.js b/lib/datasource/docker/index.ts
similarity index 87%
rename from lib/datasource/docker/index.js
rename to lib/datasource/docker/index.ts
index c0a071ee7f2e9bb61d20edad1ebb4bb7e405d483..7fa0f6a3783be80549d0d5ea7e0294817579fa02 100644
--- a/lib/datasource/docker/index.js
+++ b/lib/datasource/docker/index.ts
@@ -1,24 +1,18 @@
 import is from '@sindresorhus/is';
+import hasha from 'hasha';
+import URL from 'url';
+import parseLinkHeader from 'parse-link-header';
+import wwwAuthenticate from 'www-authenticate';
+import { logger } from '../../logger';
+import got from '../../util/got';
+import * as hostRules from '../../util/host-rules';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
-const hasha = require('hasha');
-const URL = require('url');
-const parseLinkHeader = require('parse-link-header');
-const wwwAuthenticate = require('www-authenticate');
-const { logger } = require('../../logger');
+// TODO: add got typings when available
+// TODO: replace www-authenticate with https://www.npmjs.com/package/auth-header ?
 
-const got = require('../../util/got');
-const hostRules = require('../../util/host-rules');
-
-export { getDigest, getPkgReleases };
-
-/**
- *
- * @param {string} lookupName
- * @param {string[]=} registryUrls
- */
-function getRegistryRepository(lookupName, registryUrls) {
-  /** @type string */
-  let registry;
+function getRegistryRepository(lookupName: string, registryUrls: string[]) {
+  let registry: string;
   const split = lookupName.split('/');
   if (split.length > 1 && split[0].includes('.')) {
     [registry] = split;
@@ -43,7 +37,7 @@ function getRegistryRepository(lookupName, registryUrls) {
   };
 }
 
-async function getAuthHeaders(registry, repository) {
+async function getAuthHeaders(registry: string, repository: string) {
   try {
     const apiCheckUrl = `${registry}/v2/`;
     const apiCheckResponse = await got(apiCheckUrl, { throwHttpErrors: false });
@@ -54,8 +48,9 @@ async function getAuthHeaders(registry, repository) {
       apiCheckResponse.headers['www-authenticate']
     );
 
-    /** @type any */
-    const opts = hostRules.find({ hostType: 'docker', url: apiCheckUrl });
+    const opts: hostRules.HostRule & {
+      headers?: Record<string, string>;
+    } = hostRules.find({ hostType: 'docker', url: apiCheckUrl });
     opts.json = true;
     if (opts.username && opts.password) {
       const auth = Buffer.from(`${opts.username}:${opts.password}`).toString(
@@ -124,7 +119,7 @@ async function getAuthHeaders(registry, repository) {
   }
 }
 
-function digestFromManifestStr(str) {
+function digestFromManifestStr(str: hasha.HashaInput) {
   return 'sha256:' + hasha(str, { algorithm: 'sha256' });
 }
 
@@ -135,7 +130,11 @@ function extractDigestFromResponse(manifestResponse) {
   return manifestResponse.headers['docker-content-digest'];
 }
 
-async function getManifestResponse(registry, repository, tag) {
+async function getManifestResponse(
+  registry: string,
+  repository: string,
+  tag: string
+) {
   logger.debug(`getManifestResponse(${registry}, ${repository}, ${tag})`);
   try {
     const headers = await getAuthHeaders(registry, repository);
@@ -218,10 +217,11 @@ async function getManifestResponse(registry, repository, tag) {
  * This function will:
  *  - Look up a sha256 digest for a tag on its registry
  *  - Return the digest as a string
- * @param {{registryUrls? : string[], lookupName: string}} args
- * @param {string=} newValue
  */
-async function getDigest({ registryUrls, lookupName }, newValue) {
+export async function getDigest(
+  { registryUrls, lookupName }: PkgReleaseConfig,
+  newValue?: string
+): Promise<string> {
   const { registry, repository } = getRegistryRepository(
     lookupName,
     registryUrls
@@ -265,12 +265,18 @@ async function getDigest({ registryUrls, lookupName }, newValue) {
   }
 }
 
-async function getTags(registry, repository) {
-  let tags = [];
+async function getTags(
+  registry: string,
+  repository: string
+): Promise<string[]> {
+  let tags: string[] = [];
   try {
     const cacheNamespace = 'datasource-docker-tags';
     const cacheKey = `${registry}:${repository}`;
-    const cachedResult = await renovateCache.get(cacheNamespace, cacheKey);
+    const cachedResult = await renovateCache.get<string[]>(
+      cacheNamespace,
+      cacheKey
+    );
     // istanbul ignore if
     if (cachedResult) {
       return cachedResult;
@@ -287,7 +293,16 @@ async function getTags(registry, repository) {
     }
     let page = 1;
     do {
-      const res = await got(url, { json: true, headers });
+      interface DockerTagResult {
+        body: {
+          tags: string[];
+        };
+        headers: {
+          link: string;
+        };
+      }
+
+      const res: DockerTagResult = await got(url, { json: true, headers });
       tags = tags.concat(res.body.tags);
       const linkHeader = parseLinkHeader(res.headers.link);
       url =
@@ -359,11 +374,18 @@ async function getTags(registry, repository) {
  */
 
 // istanbul ignore next
-async function getLabels(registry, repository, tag) {
+async function getLabels(
+  registry: string,
+  repository: string,
+  tag: string
+): Promise<Record<string, string>> {
   logger.debug(`getLabels(${registry}, ${repository}, ${tag})`);
   const cacheNamespace = 'datasource-docker-labels';
   const cacheKey = `${registry}:${repository}:${tag}`;
-  const cachedResult = await renovateCache.get(cacheNamespace, cacheKey);
+  const cachedResult = await renovateCache.get<Record<string, string>>(
+    cacheNamespace,
+    cacheKey
+  );
   // istanbul ignore if
   if (cachedResult) {
     return cachedResult;
@@ -397,7 +419,7 @@ async function getLabels(registry, repository, tag) {
       );
       return {};
     }
-    let labels = {};
+    let labels: Record<string, string> = {};
     const configDigest = manifest.config.digest;
     const headers = await getAuthHeaders(registry, repository);
     if (!headers) {
@@ -490,9 +512,11 @@ async function getLabels(registry, repository, tag) {
  *  - '8.1.0-alpine' is the tag
  *
  * This function will filter only tags that contain a semver version
- * @param {{lookupName :string, registryUrls?: string[]  }} args
  */
-async function getPkgReleases({ lookupName, registryUrls }) {
+export async function getPkgReleases({
+  lookupName,
+  registryUrls,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   const { registry, repository } = getRegistryRepository(
     lookupName,
     registryUrls
@@ -502,7 +526,7 @@ async function getPkgReleases({ lookupName, registryUrls }) {
     return null;
   }
   const releases = tags.map(version => ({ version }));
-  const ret = {
+  const ret: ReleaseResult = {
     dockerRegistry: registry,
     dockerRepository: repository,
     releases,
diff --git a/lib/datasource/git-tags/index.js b/lib/datasource/git-tags/index.ts
similarity index 70%
rename from lib/datasource/git-tags/index.js
rename to lib/datasource/git-tags/index.ts
index 223e356c28b1580031206e9dfe8a0a5ed8b117af..85ac2d11ab13692448e92b54770806f25267c2c6 100644
--- a/lib/datasource/git-tags/index.js
+++ b/lib/datasource/git-tags/index.ts
@@ -1,17 +1,23 @@
-const simpleGit = require('simple-git/promise');
-const semver = require('../../versioning/semver');
+import simpleGit from 'simple-git/promise';
+import * as semver from '../../versioning/semver';
+import { logger } from '../../logger';
+import { ReleaseResult, PkgReleaseConfig } from '../common';
 
 const cacheNamespace = 'git-tags';
 const cacheMinutes = 10;
-const { logger } = require('../../logger');
 
 // git will prompt for known hosts or passwords, unless we activate BatchMode
 process.env.GIT_SSH_COMMAND = 'ssh -o BatchMode=yes';
 
-async function getPkgReleases({ lookupName }) {
+export async function getPkgReleases({
+  lookupName,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   const git = simpleGit();
   try {
-    const cachedResult = await renovateCache.get(cacheNamespace, lookupName);
+    const cachedResult = await renovateCache.get<ReleaseResult>(
+      cacheNamespace,
+      lookupName
+    );
     /* istanbul ignore next line */
     if (cachedResult) return cachedResult;
 
@@ -27,7 +33,7 @@ async function getPkgReleases({ lookupName }) {
       .split('\n')
       .filter(tag => semver.isVersion(tag));
     const sourceUrl = lookupName.replace(/\.git$/, '').replace(/\/$/, '');
-    const result = {
+    const result: ReleaseResult = {
       sourceUrl,
       releases: tags.map(tag => ({
         version: semver.isValid(tag),
@@ -42,7 +48,3 @@ async function getPkgReleases({ lookupName }) {
   }
   return null;
 }
-
-module.exports = {
-  getPkgReleases,
-};
diff --git a/lib/datasource/github/index.js b/lib/datasource/github/index.ts
similarity index 77%
rename from lib/datasource/github/index.js
rename to lib/datasource/github/index.ts
index 24cb23c13d57823638dae2a11c535e71f5ada650..cd66110c61677847d527de97f415730229fdafed 100644
--- a/lib/datasource/github/index.js
+++ b/lib/datasource/github/index.ts
@@ -1,13 +1,16 @@
 import { api } from '../../platform/github/gh-got-wrapper';
-
-const { logger } = require('../../logger');
-const got = require('../../util/got');
+import {
+  ReleaseResult,
+  PkgReleaseConfig,
+  Preset,
+  DigestConfig,
+} from '../common';
+import { logger } from '../../logger';
+import got from '../../util/got';
 
 const ghGot = api.get;
 
-export { getPreset, getDigest, getPkgReleases };
-
-async function fetchJSONFile(repo, fileName) {
+async function fetchJSONFile(repo: string, fileName: string): Promise<Preset> {
   const url = `https://api.github.com/repos/${repo}/contents/${fileName}`;
   const opts = {
     headers: {
@@ -18,7 +21,7 @@ async function fetchJSONFile(repo, fileName) {
     json: true,
     hostType: 'github',
   };
-  let res;
+  let res: { body: { content: string } };
   try {
     res = await got(url, opts);
   } catch (err) {
@@ -40,7 +43,10 @@ async function fetchJSONFile(repo, fileName) {
   }
 }
 
-async function getPreset(pkgName, presetName = 'default') {
+export async function getPreset(
+  pkgName: string,
+  presetName = 'default'
+): Promise<Preset> {
   if (presetName === 'default') {
     try {
       const defaultJson = await fetchJSONFile(pkgName, 'default.json');
@@ -60,20 +66,12 @@ async function getPreset(pkgName, presetName = 'default') {
 }
 
 const cacheNamespace = 'datasource-github';
-function getCacheKey(repo, type) {
+function getCacheKey(repo: string, type: string) {
   return `${repo}:${type}`;
 }
 
-/*
- * github.getDigest
- *
- * The `newValue` supplied here should be a valid tag for the docker image.
- *
- * This function will simply return the latest commit hash for the configured repository.
- */
-
-async function getTagCommit(githubRepo, tag) {
-  const cachedResult = await renovateCache.get(
+async function getTagCommit(githubRepo: string, tag: string): Promise<string> {
+  const cachedResult = await renovateCache.get<string>(
     cacheNamespace,
     getCacheKey(githubRepo, `tag-${tag}`)
   );
@@ -81,7 +79,7 @@ async function getTagCommit(githubRepo, tag) {
   if (cachedResult) {
     return cachedResult;
   }
-  let digest;
+  let digest: string;
   try {
     const url = `https://api.github.com/repos/${githubRepo}/git/refs/tags/${tag}`;
     const res = (await ghGot(url)).body.object;
@@ -111,7 +109,17 @@ async function getTagCommit(githubRepo, tag) {
   return digest;
 }
 
-async function getDigest({ lookupName: githubRepo }, newValue) {
+/**
+ * github.getDigest
+ *
+ * The `newValue` supplied here should be a valid tag for the docker image.
+ *
+ * This function will simply return the latest commit hash for the configured repository.
+ */
+export async function getDigest(
+  { lookupName: githubRepo }: Partial<DigestConfig>,
+  newValue?: string
+): Promise<string> {
   if (newValue && newValue.length) {
     return getTagCommit(githubRepo, newValue);
   }
@@ -123,7 +131,7 @@ async function getDigest({ lookupName: githubRepo }, newValue) {
   if (cachedResult) {
     return cachedResult;
   }
-  let digest;
+  let digest: string;
   try {
     const url = `https://api.github.com/repos/${githubRepo}/commits?per_page=1`;
     digest = (await ghGot(url)).body[0].sha;
@@ -146,7 +154,7 @@ async function getDigest({ lookupName: githubRepo }, newValue) {
   return digest;
 }
 
-/*
+/**
  * github.getPkgReleases
  *
  * This function can be used to fetch releases with a customisable version scheme (e.g. semver) and with either tags or releases.
@@ -156,10 +164,12 @@ async function getDigest({ lookupName: githubRepo }, newValue) {
  *  - Sanitize the versions if desired (e.g. strip out leading 'v')
  *  - Return a dependency object containing sourceUrl string and releases array
  */
-
-async function getPkgReleases({ lookupName: repo, lookupType }) {
-  let versions;
-  const cachedResult = await renovateCache.get(
+export async function getPkgReleases({
+  lookupName: repo,
+  lookupType,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
+  let versions: string[];
+  const cachedResult = await renovateCache.get<ReleaseResult>(
     cacheNamespace,
     getCacheKey(repo, lookupType || 'tags')
   );
@@ -170,13 +180,21 @@ async function getPkgReleases({ lookupName: repo, lookupType }) {
   try {
     if (lookupType === 'releases') {
       const url = `https://api.github.com/repos/${repo}/releases?per_page=100`;
-      versions = (await ghGot(url, { paginate: true })).body.map(
-        o => o.tag_name
-      );
+      type GitHubRelease = {
+        tag_name: string;
+      }[];
+
+      versions = (await ghGot<GitHubRelease>(url, {
+        paginate: true,
+      })).body.map(o => o.tag_name);
     } else {
       // tag
       const url = `https://api.github.com/repos/${repo}/tags?per_page=100`;
-      versions = (await ghGot(url, {
+      type GitHubTag = {
+        name: string;
+      }[];
+
+      versions = (await ghGot<GitHubTag>(url, {
         paginate: true,
       })).body.map(o => o.name);
     }
@@ -186,8 +204,9 @@ async function getPkgReleases({ lookupName: repo, lookupType }) {
   if (!versions) {
     return null;
   }
-  const dependency = {
+  const dependency: ReleaseResult = {
     sourceUrl: 'https://github.com/' + repo,
+    releases: null,
   };
   dependency.releases = versions.map(version => ({
     version,
diff --git a/lib/datasource/gitlab/index.js b/lib/datasource/gitlab/index.ts
similarity index 69%
rename from lib/datasource/gitlab/index.js
rename to lib/datasource/gitlab/index.ts
index a4a016934a04f4e50b4469c4dc472320845a9d6f..d309275c4f89c0e32ad27a4057f92326427cb9ac 100644
--- a/lib/datasource/gitlab/index.js
+++ b/lib/datasource/gitlab/index.ts
@@ -1,21 +1,25 @@
 import is from '@sindresorhus/is';
+import { api } from '../../platform/gitlab/gl-got-wrapper';
+import { logger } from '../../logger';
+import { PkgReleaseConfig, ReleaseResult, Preset } from '../common';
 
-const glGot = require('../../platform/gitlab/gl-got-wrapper').api.get;
-const { logger } = require('../../logger');
-
-export { getPreset, getPkgReleases };
+const glGot = api.get;
 
 const GitLabApiUrl = 'https://gitlab.com/api/v4/projects';
 
-async function getPreset(pkgName, presetName = 'default') {
+export async function getPreset(
+  pkgName: string,
+  presetName = 'default'
+): Promise<Preset> {
   if (presetName !== 'default') {
+    // TODO: proper error contructor
     throw new Error(
       { pkgName, presetName },
       // @ts-ignore
       'Sub-preset names are not supported with Gitlab datasource'
     );
   }
-  let res;
+  let res: string;
   try {
     const urlEncodedPkgName = encodeURIComponent(pkgName);
     const defautlBranchName = await getDefaultBranchName(urlEncodedPkgName);
@@ -38,22 +42,22 @@ async function getPreset(pkgName, presetName = 'default') {
 }
 
 const cacheNamespace = 'datasource-gitlab';
-function getCacheKey(depHost, repo, lookupType) {
+function getCacheKey(depHost: string, repo: string, lookupType: string) {
   const type = lookupType || 'tags';
   return `${depHost}:${repo}:${type}`;
 }
 
-/**
- *
- * @param {{registryUrls? : string[], lookupName:string, lookupType:string}} param0
- */
-async function getPkgReleases({ registryUrls, lookupName: repo, lookupType }) {
+export async function getPkgReleases({
+  registryUrls,
+  lookupName: repo,
+  lookupType,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   // Use registryUrls if present, otherwise default to publid gitlab.com
   const depHost = is.nonEmptyArray(registryUrls)
     ? registryUrls[0].replace(/\/$/, '')
     : 'https://gitlab.com';
-  let versions;
-  const cachedResult = await renovateCache.get(
+  let versions: string[];
+  const cachedResult = await renovateCache.get<ReleaseResult>(
     cacheNamespace,
     getCacheKey(depHost, repo, lookupType)
   );
@@ -67,13 +71,21 @@ async function getPkgReleases({ registryUrls, lookupName: repo, lookupType }) {
   try {
     if (lookupType === 'releases') {
       const url = `${depHost}/api/v4/projects/${urlEncodedRepo}/releases?per_page=100`;
-      versions = (await glGot(url, { paginate: true })).body.map(
-        o => o.tag_name
-      );
+      type GlRelease = {
+        tag_name: string;
+      }[];
+
+      versions = (await glGot<GlRelease>(url, {
+        paginate: true,
+      })).body.map(o => o.tag_name);
     } else {
       // tag
       const url = `${depHost}/api/v4/projects/${urlEncodedRepo}/repository/tags?per_page=100`;
-      versions = (await glGot(url, {
+      type GlTag = {
+        name: string;
+      }[];
+
+      versions = (await glGot<GlTag>(url, {
         paginate: true,
       })).body.map(o => o.name);
     }
@@ -87,8 +99,9 @@ async function getPkgReleases({ registryUrls, lookupName: repo, lookupType }) {
     return null;
   }
 
-  const dependency = {
+  const dependency: ReleaseResult = {
     sourceUrl: `${depHost}/${repo}`,
+    releases: null,
   };
   dependency.releases = versions.map(version => ({
     version,
@@ -105,9 +118,14 @@ async function getPkgReleases({ registryUrls, lookupName: repo, lookupType }) {
   return dependency;
 }
 
-async function getDefaultBranchName(urlEncodedPkgName) {
+async function getDefaultBranchName(urlEncodedPkgName: string) {
   const branchesUrl = `${GitLabApiUrl}/${urlEncodedPkgName}/repository/branches`;
-  const res = await glGot(branchesUrl);
+  type GlBranch = {
+    default: boolean;
+    name: string;
+  }[];
+
+  const res = await glGot<GlBranch>(branchesUrl);
   const branches = res.body;
   let defautlBranchName = 'master';
   for (const branch of branches) {
diff --git a/lib/datasource/go/index.js b/lib/datasource/go/index.ts
similarity index 83%
rename from lib/datasource/go/index.js
rename to lib/datasource/go/index.ts
index e44d1aab7a5429d997843b88672cbee9bb35a5db..f1963f09f505ab471a25ac42a3b52b118e688f89 100644
--- a/lib/datasource/go/index.js
+++ b/lib/datasource/go/index.ts
@@ -1,13 +1,14 @@
-const { logger } = require('../../logger');
-const got = require('../../util/got');
-const github = require('../github');
+import { logger } from '../../logger';
+import got from '../../util/got';
+import * as github from '../github';
+import { DigestConfig, PkgReleaseConfig, ReleaseResult } from '../common';
 
-module.exports = {
-  getPkgReleases,
-  getDigest,
-};
+interface DataSource {
+  datasource: string;
+  lookupName: string;
+}
 
-async function getDatasource(name) {
+async function getDatasource(name: string): Promise<DataSource> {
   if (name.startsWith('gopkg.in/')) {
     const [pkg] = name.replace('gopkg.in/', '').split('.');
     if (pkg.includes('/')) {
@@ -59,7 +60,7 @@ async function getDatasource(name) {
   }
 }
 
-/*
+/**
  * go.getPkgReleases
  *
  * This datasource resolves a go module URL into its source repository
@@ -69,12 +70,12 @@ async function getDatasource(name) {
  *  - Determine the source URL for the module
  *  - Call the respective getPkgReleases in github to retrieve the tags
  */
-
-async function getPkgReleases({ lookupName }) {
+export async function getPkgReleases({
+  lookupName,
+}: Partial<PkgReleaseConfig>): Promise<ReleaseResult> {
   logger.trace(`go.getPkgReleases(${lookupName})`);
   const source = await getDatasource(lookupName);
   if (source && source.datasource === 'github') {
-    // @ts-ignore
     const res = await github.getPkgReleases(source);
     if (res && res.releases) {
       res.releases = res.releases.filter(
@@ -86,7 +87,7 @@ async function getPkgReleases({ lookupName }) {
   return null;
 }
 
-/*
+/**
  * go.getDigest
  *
  * This datasource resolves a go module URL into its source repository
@@ -96,8 +97,10 @@ async function getPkgReleases({ lookupName }) {
  *  - Determine the source URL for the module
  *  - Call the respective getDigest in github to retrieve the commit hash
  */
-
-async function getDigest({ lookupName }, value) {
+export async function getDigest(
+  { lookupName }: Partial<DigestConfig>,
+  value?: string
+): Promise<string> {
   const source = await getDatasource(lookupName);
   if (source && source.datasource === 'github') {
     // ignore v0.0.0- pseudo versions that are used Go Modules - look up default branch instead
diff --git a/lib/datasource/gradle-version/index.js b/lib/datasource/gradle-version/index.ts
similarity index 63%
rename from lib/datasource/gradle-version/index.js
rename to lib/datasource/gradle-version/index.ts
index ae6fc021c1c3e618224d45d5ada6807be7cef87b..6adaa7eb9df3f8c54c1c457577be84c9ca949676 100644
--- a/lib/datasource/gradle-version/index.js
+++ b/lib/datasource/gradle-version/index.ts
@@ -1,16 +1,26 @@
-const { coerce } = require('semver');
-const { logger } = require('../../logger');
-const got = require('../../util/got');
-
-module.exports = {
-  getPkgReleases,
-};
+import { coerce } from 'semver';
+import { logger } from '../../logger';
+import got from '../../util/got';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
 const GradleVersionsServiceUrl = 'https://services.gradle.org/versions/all';
 
-async function getPkgReleases() {
+interface GradleRelease {
+  body: {
+    snapshot?: boolean;
+    nightly?: boolean;
+    rcFor?: string;
+    version: string;
+    downloadUrl?: string;
+    checksumUrl?: string;
+  }[];
+}
+
+export async function getPkgReleases(
+  _config: PkgReleaseConfig
+): Promise<ReleaseResult> {
   try {
-    const response = await got(GradleVersionsServiceUrl, {
+    const response: GradleRelease = await got(GradleVersionsServiceUrl, {
       json: true,
     });
     const releases = response.body
@@ -25,7 +35,7 @@ async function getPkgReleases() {
         downloadUrl: release.downloadUrl,
         checksumUrl: release.checksumUrl,
       }));
-    const gradle = {
+    const gradle: ReleaseResult = {
       releases,
       homepage: 'https://gradle.org',
       sourceUrl: 'https://github.com/gradle/gradle',
diff --git a/lib/datasource/hex/index.js b/lib/datasource/hex/index.ts
similarity index 72%
rename from lib/datasource/hex/index.js
rename to lib/datasource/hex/index.ts
index 3db55774d3017a48a7cd06ed5d06d5391fdf582c..3364512cd9c2c46057cebb30facc51c3ed040e5a 100644
--- a/lib/datasource/hex/index.js
+++ b/lib/datasource/hex/index.ts
@@ -1,9 +1,6 @@
-const { logger } = require('../../logger');
-const got = require('../../util/got');
-
-module.exports = {
-  getPkgReleases,
-};
+import { logger } from '../../logger';
+import got from '../../util/got';
+import { ReleaseResult, PkgReleaseConfig } from '../common';
 
 function getHostOpts() {
   return {
@@ -12,11 +9,20 @@ function getHostOpts() {
   };
 }
 
-async function getPkgReleases({ lookupName }) {
+interface HexRelease {
+  html_url: string;
+  meta?: { links?: Record<string, string> };
+  name?: string;
+  releases?: { version: string }[];
+}
+
+export async function getPkgReleases({
+  lookupName,
+}: Partial<PkgReleaseConfig>): Promise<ReleaseResult> {
   const hexUrl = `https://hex.pm/api/packages/${lookupName}`;
   try {
     const opts = getHostOpts();
-    const res = (await got(hexUrl, {
+    const res: HexRelease = (await got(hexUrl, {
       json: true,
       ...opts,
     })).body;
@@ -24,7 +30,7 @@ async function getPkgReleases({ lookupName }) {
       logger.warn({ lookupName }, `Received invalid hex package data`);
       return null;
     }
-    const result = {
+    const result: ReleaseResult = {
       releases: [],
     };
     if (res.releases) {
diff --git a/lib/datasource/index.js b/lib/datasource/index.ts
similarity index 56%
rename from lib/datasource/index.js
rename to lib/datasource/index.ts
index b244dc11f4d24cdbaba27a7f9321351b7c59c038..c677ca1a37ff9aa29d2214e3ac9d740c7e70646a 100644
--- a/lib/datasource/index.js
+++ b/lib/datasource/index.ts
@@ -1,28 +1,37 @@
-const { logger } = require('../logger');
-const { addMetaData } = require('./metadata');
-const versioning = require('../versioning');
+import { logger } from '../logger';
+import { addMetaData } from './metadata';
+import * as versioning from '../versioning';
 
-const cargo = require('./cargo');
-const dart = require('./dart');
-const docker = require('./docker');
-const hex = require('./hex');
-const github = require('./github');
-const gitlab = require('./gitlab');
-const gitTags = require('./git-tags');
-const go = require('./go');
-const gradleVersion = require('./gradle-version');
-const maven = require('./maven');
-const npm = require('./npm');
-const nuget = require('./nuget');
-const orb = require('./orb');
-const packagist = require('./packagist');
-const pypi = require('./pypi');
-const rubygems = require('./rubygems');
-const rubyVersion = require('./ruby-version');
-const sbt = require('./sbt');
-const terraform = require('./terraform');
+import * as cargo from './cargo';
+import * as dart from './dart';
+import * as docker from './docker';
+import * as hex from './hex';
+import * as github from './github';
+import * as gitlab from './gitlab';
+import * as gitTags from './git-tags';
+import * as go from './go';
+import * as gradleVersion from './gradle-version';
+import * as maven from './maven';
+import * as npm from './npm';
+import * as nuget from './nuget';
+import * as orb from './orb';
+import * as packagist from './packagist';
+import * as pypi from './pypi';
+import * as rubygems from './rubygems';
+import * as rubyVersion from './ruby-version';
+import * as sbt from './sbt';
+import * as terraform from './terraform';
+import {
+  Datasource,
+  PkgReleaseConfig,
+  Release,
+  ReleaseResult,
+  DigestConfig,
+} from './common';
 
-const datasources = {
+export * from './common';
+
+const datasources: Record<string, Datasource> = {
   cargo,
   dart,
   docker,
@@ -46,7 +55,7 @@ const datasources = {
 
 const cacheNamespace = 'datasource-releases';
 
-async function getPkgReleases(config) {
+export async function getPkgReleases(config: PkgReleaseConfig) {
   const res = await getRawReleases({
     ...config,
     lookupName: config.lookupName || config.depName,
@@ -59,7 +68,7 @@ async function getPkgReleases(config) {
   // Filter by version scheme
   const version = versioning.get(versionScheme);
   // Return a sorted list of valid Versions
-  function sortReleases(release1, release2) {
+  function sortReleases(release1: Release, release2: Release) {
     return version.sortVersions(release1.version, release2.version);
   }
   if (res.releases) {
@@ -70,7 +79,7 @@ async function getPkgReleases(config) {
   return res;
 }
 
-function getRawReleases(config) {
+function getRawReleases(config: PkgReleaseConfig): Promise<ReleaseResult> {
   const cacheKey =
     cacheNamespace +
     config.datasource +
@@ -84,7 +93,7 @@ function getRawReleases(config) {
   return global.repoCache[cacheKey];
 }
 
-async function fetchReleases(config) {
+async function fetchReleases(config: PkgReleaseConfig): Promise<ReleaseResult> {
   const { datasource } = config;
   if (!datasource) {
     logger.warn('No datasource found');
@@ -98,11 +107,11 @@ async function fetchReleases(config) {
   return dep;
 }
 
-function supportsDigests(config) {
+export function supportsDigests(config: DigestConfig) {
   return !!datasources[config.datasource].getDigest;
 }
 
-function getDigest(config, value) {
+export function getDigest(config: DigestConfig, value?: string) {
   const lookupName = config.lookupName || config.depName;
   const { registryUrls } = config;
   return datasources[config.datasource].getDigest(
@@ -110,9 +119,3 @@ function getDigest(config, value) {
     value
   );
 }
-
-module.exports = {
-  getPkgReleases,
-  supportsDigests,
-  getDigest,
-};
diff --git a/lib/datasource/maven/index.js b/lib/datasource/maven/index.ts
similarity index 78%
rename from lib/datasource/maven/index.js
rename to lib/datasource/maven/index.ts
index 732f9fbd4694a22bc1c678db72685fceb0532ec6..455546f922118cc0cf1317d8a8d6aff6f9fab2c0 100644
--- a/lib/datasource/maven/index.js
+++ b/lib/datasource/maven/index.ts
@@ -1,23 +1,18 @@
 import is from '@sindresorhus/is';
-
-const url = require('url');
-const fs = require('fs-extra');
-const { XmlDocument } = require('xmldoc');
-const { logger } = require('../../logger');
-
-const { compare } = require('../../versioning/maven/compare');
-const { containsPlaceholder } = require('../../manager/maven/extract');
-const { downloadHttpProtocol } = require('./util');
-
-export { getPkgReleases };
-
-/**
- *
- * @param {{lookupName:string, registryUrls?: string[]}} args
- */
-// eslint-disable-next-line no-unused-vars
-async function getPkgReleases({ lookupName, registryUrls }) {
-  const versions = [];
+import url from 'url';
+import fs from 'fs-extra';
+import { XmlDocument } from 'xmldoc';
+import { logger } from '../../logger';
+import { compare } from '../../versioning/maven/compare';
+import { containsPlaceholder } from '../../manager/maven/extract';
+import { downloadHttpProtocol } from './util';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
+
+export async function getPkgReleases({
+  lookupName,
+  registryUrls,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
+  const versions: string[] = [];
   const dependency = getDependencyParts(lookupName);
   if (!is.nonEmptyArray(registryUrls)) {
     logger.warn(`No repositories defined for ${dependency.display}`);
@@ -84,13 +79,24 @@ function getDependencyParts(lookupName) {
   };
 }
 
-async function downloadMavenXml(dependency, repoUrl, dependencyFilePath) {
+interface MavenDependency {
+  display: string;
+  group?: string;
+  name?: string;
+  dependencyUrl: string;
+}
+
+async function downloadMavenXml(
+  dependency: MavenDependency,
+  repoUrl: string,
+  dependencyFilePath: string
+) {
   const pkgUrl = new url.URL(
     `${dependency.dependencyUrl}/${dependencyFilePath}`,
     repoUrl
   );
 
-  let rawContent;
+  let rawContent: string;
   switch (pkgUrl.protocol) {
     case 'file:':
       rawContent = await downloadFileProtocol(pkgUrl);
@@ -122,14 +128,14 @@ async function downloadMavenXml(dependency, repoUrl, dependencyFilePath) {
   }
 }
 
-function extractVersions(metadata) {
+function extractVersions(metadata: XmlDocument) {
   const versions = metadata.descendantWithPath('versioning.versions');
   const elements = versions && versions.childrenNamed('version');
   if (!elements) return [];
   return elements.map(el => el.val);
 }
 
-async function downloadFileProtocol(pkgUrl) {
+async function downloadFileProtocol(pkgUrl: url.URL) {
   const pkgPath = pkgUrl.toString().replace('file://', '');
   if (!(await fs.exists(pkgPath))) {
     return null;
@@ -137,15 +143,19 @@ async function downloadFileProtocol(pkgUrl) {
   return fs.readFile(pkgPath, 'utf8');
 }
 
-function getLatestVersion(versions) {
+function getLatestVersion(versions: string[]) {
   if (versions.length === 0) return null;
   return versions.reduce((latestVersion, version) =>
     compare(version, latestVersion) === 1 ? version : latestVersion
   );
 }
 
-async function getDependencyInfo(dependency, repoUrl, version) {
-  const result = {};
+async function getDependencyInfo(
+  dependency: MavenDependency,
+  repoUrl: string,
+  version: string
+) {
+  const result: Partial<ReleaseResult> = {};
   const path = `${version}/${dependency.name}-${version}.pom`;
 
   const pomContent = await downloadMavenXml(dependency, repoUrl, path);
diff --git a/lib/datasource/maven/util.js b/lib/datasource/maven/util.ts
similarity index 70%
rename from lib/datasource/maven/util.js
rename to lib/datasource/maven/util.ts
index 4c89618ddd6e112129b4f5e35799f7f80417509f..9b1b1b8e76966a255bfcdfe93c28bffb3b33bc8e 100644
--- a/lib/datasource/maven/util.js
+++ b/lib/datasource/maven/util.ts
@@ -1,20 +1,14 @@
-const got = require('../../util/got');
-const { logger } = require('../../logger');
+import url from 'url';
+import got from '../../util/got';
+import { logger } from '../../logger';
 
-module.exports = {
-  downloadHttpProtocol,
-};
-
-/**
- * @param {import('url').URL | string} pkgUrl
- */
-function isMavenCentral(pkgUrl) {
+function isMavenCentral(pkgUrl: url.URL | string) {
   return (
     (typeof pkgUrl === 'string' ? pkgUrl : pkgUrl.host) === 'central.maven.org'
   );
 }
 
-function isTemporalError(err) {
+function isTemporalError(err: { code: string; statusCode: number }) {
   return (
     err.code === 'ECONNRESET' ||
     err.statusCode === 429 ||
@@ -22,24 +16,27 @@ function isTemporalError(err) {
   );
 }
 
-function isHostError(err) {
+function isHostError(err: { code: string }) {
   return err.code === 'ETIMEDOUT';
 }
 
-function isNotFoundError(err) {
+function isNotFoundError(err: { code: string; statusCode: number }) {
   return err.code === 'ENOTFOUND' || err.statusCode === 404;
 }
 
-function isPermissionsIssue(err) {
+function isPermissionsIssue(err: { statusCode: number }) {
   return err.statusCode === 401 || err.statusCode === 403;
 }
 
-function isConnectionError(err) {
+function isConnectionError(err: { code: string }) {
   return err.code === 'ECONNREFUSED';
 }
 
-async function downloadHttpProtocol(pkgUrl, hostType = 'maven') {
-  let raw;
+export async function downloadHttpProtocol(
+  pkgUrl: url.URL | string,
+  hostType = 'maven'
+) {
+  let raw: { body: string };
   try {
     raw = await got(pkgUrl, { hostType });
   } catch (err) {
diff --git a/lib/datasource/metadata.js b/lib/datasource/metadata.ts
similarity index 95%
rename from lib/datasource/metadata.js
rename to lib/datasource/metadata.ts
index 885d4b0f1eb82f36b9d28aada502c1f91d4759d4..4f451957d47356291e45de1f39c49494940e767b 100644
--- a/lib/datasource/metadata.js
+++ b/lib/datasource/metadata.ts
@@ -1,8 +1,6 @@
 import is from '@sindresorhus/is';
-
-const parse = require('github-url-from-git');
-
-export { addMetaData };
+import parse from 'github-url-from-git';
+import { ReleaseResult } from './common';
 
 // Use this object to define changelog URLs for packages
 // Only necessary when the changelog data cannot be found in the package's source repository
@@ -65,7 +63,11 @@ const manualSourceUrls = {
 };
 
 /* eslint-disable no-param-reassign */
-function addMetaData(dep, datasource, lookupName) {
+export function addMetaData(
+  dep?: ReleaseResult,
+  datasource?: string,
+  lookupName?: string
+) {
   if (!dep) {
     return;
   }
diff --git a/lib/datasource/npm/get.js b/lib/datasource/npm/get.ts
similarity index 83%
rename from lib/datasource/npm/get.js
rename to lib/datasource/npm/get.ts
index a3c5f77733cc196c997100c075bd7043dd538911..7291a848218a05829b91acee21f92ee1deb06a0a 100644
--- a/lib/datasource/npm/get.js
+++ b/lib/datasource/npm/get.ts
@@ -1,34 +1,46 @@
-const moment = require('moment');
-const url = require('url');
-const getRegistryUrl = require('registry-auth-token/registry-url');
-const registryAuthToken = require('registry-auth-token');
-const parse = require('github-url-from-git');
-const { isBase64 } = require('validator');
-const { logger } = require('../../logger');
-
-const got = require('../../util/got');
-const hostRules = require('../../util/host-rules');
-const { maskToken } = require('../../util/mask');
-const { getNpmrc } = require('./npmrc');
-
-module.exports = {
-  getDependency,
-  resetCache,
-  resetMemCache,
-};
+import moment from 'moment';
+import url from 'url';
+import getRegistryUrl from 'registry-auth-token/registry-url';
+import registryAuthToken from 'registry-auth-token';
+import parse from 'github-url-from-git';
+import { isBase64 } from 'validator';
+import { OutgoingHttpHeaders } from 'http';
+import { logger } from '../../logger';
+import got from '../../util/got';
+import * as hostRules from '../../util/host-rules';
+import { maskToken } from '../../util/mask';
+import { getNpmrc } from './npmrc';
+import { Release, ReleaseResult } from '../common';
 
 let memcache = {};
 
-function resetMemCache() {
+export function resetMemCache() {
   logger.debug('resetMemCache()');
   memcache = {};
 }
 
-function resetCache() {
+export function resetCache() {
   resetMemCache();
 }
 
-async function getDependency(name) {
+export interface NpmRelease extends Release {
+  canBeUnpublished?: boolean;
+  gitRef?: string;
+}
+export interface NpmDependency extends ReleaseResult {
+  releases: NpmRelease[];
+  deprecationSource?: string;
+  name: string;
+  homepage: string;
+  latestVersion: string;
+  sourceUrl: string;
+  versions: Record<string, any>;
+  'dist-tags': string[];
+  'renovate-config': any;
+  sourceDirectory?: string;
+}
+
+export async function getDependency(name: string): Promise<NpmDependency> {
   logger.trace(`npm.getDependency(${name})`);
 
   // This is our datastore cache and is cleared at the end of each repo, i.e. we never requery/revalidate during a "run"
@@ -38,7 +50,7 @@ async function getDependency(name) {
   }
 
   const scope = name.split('/')[0];
-  let regUrl;
+  let regUrl: string;
   const npmrc = getNpmrc();
   try {
     regUrl = getRegistryUrl(scope, npmrc);
@@ -51,12 +63,15 @@ async function getDependency(name) {
   );
   // Now check the persistent cache
   const cacheNamespace = 'datasource-npm';
-  const cachedResult = await renovateCache.get(cacheNamespace, pkgUrl);
+  const cachedResult = await renovateCache.get<NpmDependency>(
+    cacheNamespace,
+    pkgUrl
+  );
   if (cachedResult) {
     return cachedResult;
   }
   const authInfo = registryAuthToken(regUrl, { npmrc });
-  const headers = {};
+  const headers: OutgoingHttpHeaders = {};
 
   if (authInfo && authInfo.type && authInfo.token) {
     // istanbul ignore if
@@ -125,7 +140,7 @@ async function getDependency(name) {
     res.homepage = res.homepage || latestVersion.homepage;
 
     // Determine repository URL
-    let sourceUrl;
+    let sourceUrl: string;
 
     if (res.repository && res.repository.url) {
       const extraBaseUrls = [];
@@ -155,12 +170,13 @@ async function getDependency(name) {
       delete res.homepage;
     }
     // Simplify response before caching and returning
-    const dep = {
+    const dep: NpmDependency = {
       name: res.name,
       homepage: res.homepage,
       latestVersion: res['dist-tags'].latest,
       sourceUrl,
       versions: {},
+      releases: null,
       'dist-tags': res['dist-tags'],
       'renovate-config': latestVersion['renovate-config'],
     };
@@ -172,7 +188,7 @@ async function getDependency(name) {
       dep.deprecationSource = 'npm';
     }
     dep.releases = Object.keys(res.versions).map(version => {
-      const release = {
+      const release: NpmRelease = {
         version,
         gitRef: res.versions[version].gitHead,
       };
diff --git a/lib/datasource/npm/index.js b/lib/datasource/npm/index.js
deleted file mode 100644
index 5485934deb3e4c1477a16768aaa681ca34debd8b..0000000000000000000000000000000000000000
--- a/lib/datasource/npm/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const { resetMemCache, resetCache } = require('./get');
-const { getPreset } = require('./presets');
-const { getPkgReleases } = require('./releases');
-const { setNpmrc } = require('./npmrc');
-
-module.exports = {
-  setNpmrc,
-  getPreset,
-  getPkgReleases,
-  resetMemCache,
-  resetCache,
-};
diff --git a/lib/datasource/npm/index.ts b/lib/datasource/npm/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c4fc281955210e20437ed86cc8667f73d788798f
--- /dev/null
+++ b/lib/datasource/npm/index.ts
@@ -0,0 +1,4 @@
+export { resetMemCache, resetCache } from './get';
+export { getPreset } from './presets';
+export { getPkgReleases } from './releases';
+export { setNpmrc } from './npmrc';
diff --git a/lib/datasource/npm/npmrc.js b/lib/datasource/npm/npmrc.ts
similarity index 84%
rename from lib/datasource/npm/npmrc.js
rename to lib/datasource/npm/npmrc.ts
index d9093a8a0cf98ba87745b4f4dcc3a08ba79d0e61..7f6fa8e26fa6aeee19909439d8b561188b94e860 100644
--- a/lib/datasource/npm/npmrc.js
+++ b/lib/datasource/npm/npmrc.ts
@@ -1,19 +1,16 @@
 import is from '@sindresorhus/is';
+import ini from 'ini';
+import { isBase64 } from 'validator';
+import { logger } from '../../logger';
 
-const ini = require('ini');
-const { isBase64 } = require('validator');
-const { logger } = require('../../logger');
+let npmrc: Record<string, any> = null;
+let npmrcRaw: string;
 
-let npmrc = null;
-let npmrcRaw;
-
-export { getNpmrc, setNpmrc };
-
-function getNpmrc() {
+export function getNpmrc() {
   return npmrc;
 }
 
-function setNpmrc(input) {
+export function setNpmrc(input?: string) {
   if (input) {
     if (input === npmrcRaw) {
       return;
@@ -60,7 +57,7 @@ function setNpmrc(input) {
   }
 }
 
-function envReplace(value, env = process.env) {
+function envReplace(value: any, env = process.env) {
   // istanbul ignore if
   if (!is.string(value)) {
     return value;
diff --git a/lib/datasource/npm/presets.js b/lib/datasource/npm/presets.ts
similarity index 76%
rename from lib/datasource/npm/presets.js
rename to lib/datasource/npm/presets.ts
index b7137f3e0331cefdf5f3f62d575dc8203de65a04..dbe911b329fd2d94d5d77e165aa5733df6faed5f 100644
--- a/lib/datasource/npm/presets.js
+++ b/lib/datasource/npm/presets.ts
@@ -1,10 +1,11 @@
 import { logger } from '../../logger';
+import { getDependency } from './get';
+import { Preset } from '../common';
 
-const { getDependency } = require('./get');
-
-export { getPreset };
-
-async function getPreset(pkgName, presetName = 'default') {
+export async function getPreset(
+  pkgName: string,
+  presetName = 'default'
+): Promise<Preset> {
   const dep = await getDependency(pkgName);
   if (!dep) {
     throw new Error('dep not found');
diff --git a/lib/datasource/npm/releases.js b/lib/datasource/npm/releases.js
deleted file mode 100644
index f2c96a675627edc201340df756beec0fd1be3d75..0000000000000000000000000000000000000000
--- a/lib/datasource/npm/releases.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const { getDependency } = require('./get');
-const { setNpmrc } = require('./npmrc');
-
-module.exports = {
-  getPkgReleases,
-};
-
-/**
- *
- * @param {{lookupName: string, npmrc?: string}} args
- */
-async function getPkgReleases({ lookupName, npmrc }) {
-  if (npmrc) {
-    setNpmrc(npmrc);
-  }
-  const res = await getDependency(lookupName);
-  if (res) {
-    res.tags = res['dist-tags'];
-    delete res['dist-tags'];
-    delete res['renovate-config'];
-  }
-  return res;
-}
diff --git a/lib/datasource/npm/releases.ts b/lib/datasource/npm/releases.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d2d887d46c61d2179250781d545234add8ac843e
--- /dev/null
+++ b/lib/datasource/npm/releases.ts
@@ -0,0 +1,19 @@
+import { getDependency } from './get';
+import { setNpmrc } from './npmrc';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
+
+export async function getPkgReleases({
+  lookupName,
+  npmrc,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
+  if (npmrc) {
+    setNpmrc(npmrc);
+  }
+  const res: ReleaseResult = await getDependency(lookupName);
+  if (res) {
+    res.tags = res['dist-tags'];
+    delete res['dist-tags'];
+    delete res['renovate-config'];
+  }
+  return res;
+}
diff --git a/lib/datasource/nuget/index.js b/lib/datasource/nuget/index.ts
similarity index 71%
rename from lib/datasource/nuget/index.js
rename to lib/datasource/nuget/index.ts
index b4399c564ced0045c5ba9fe61e45927764e69431..56a1c108ec82baf858e867a621d70b8f0b730b2f 100644
--- a/lib/datasource/nuget/index.js
+++ b/lib/datasource/nuget/index.ts
@@ -1,15 +1,15 @@
-const urlApi = require('url');
-const { logger } = require('../../logger');
-const v2 = require('./v2');
-const v3 = require('./v3');
+import urlApi from 'url';
+import { logger } from '../../logger';
+import * as v2 from './v2';
+import * as v3 from './v3';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
-module.exports = {
-  getPkgReleases,
-};
-
-async function getPkgReleases({ lookupName, registryUrls }) {
+export async function getPkgReleases({
+  lookupName,
+  registryUrls,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   logger.trace(`nuget.getPkgReleases(${lookupName})`);
-  let dep = null;
+  let dep: ReleaseResult = null;
   for (const feed of registryUrls || [v3.getDefaultFeed()]) {
     const feedVersion = detectFeedVersion(feed);
     if (feedVersion === 2) {
@@ -33,7 +33,7 @@ async function getPkgReleases({ lookupName, registryUrls }) {
   return dep;
 }
 
-function detectFeedVersion(url) {
+function detectFeedVersion(url: string) {
   try {
     const parsecUrl = urlApi.parse(url);
     // Official client does it in the same way
diff --git a/lib/datasource/nuget/v2.js b/lib/datasource/nuget/v2.ts
similarity index 80%
rename from lib/datasource/nuget/v2.js
rename to lib/datasource/nuget/v2.ts
index d18d0f366a3c17d5a5db90fcb0f5a4cdec6180fd..0297b8e4c3e305213c15529bb2cb559f91b2d727 100644
--- a/lib/datasource/nuget/v2.js
+++ b/lib/datasource/nuget/v2.ts
@@ -1,15 +1,16 @@
-const parse = require('github-url-from-git');
-const { XmlDocument } = require('xmldoc');
-const { logger } = require('../../logger');
-const got = require('../../util/got');
+import parse from 'github-url-from-git';
+import { XmlDocument, XmlElement } from 'xmldoc';
+import { logger } from '../../logger';
+import got from '../../util/got';
+import { ReleaseResult } from '../common';
 
-module.exports = {
-  getPkgReleases,
-};
-
-async function getPkgReleases(feedUrl, pkgName) {
-  const dep = {
+export async function getPkgReleases(
+  feedUrl: string,
+  pkgName: string
+): Promise<ReleaseResult> {
+  const dep: ReleaseResult = {
     pkgName,
+    releases: null,
   };
   try {
     dep.releases = [];
@@ -64,6 +65,6 @@ async function getPkgReleases(feedUrl, pkgName) {
   }
 }
 
-function getPkgProp(pkgInfo, propName) {
+function getPkgProp(pkgInfo: XmlElement, propName: string) {
   return pkgInfo.childNamed('m:properties').childNamed(`d:${propName}`).val;
 }
diff --git a/lib/datasource/nuget/v3.js b/lib/datasource/nuget/v3.ts
similarity index 85%
rename from lib/datasource/nuget/v3.js
rename to lib/datasource/nuget/v3.ts
index 18965f52fa768662930fca4dfe260182bf7b022f..06c3b5b88e5c240e7790a77d2b0de69cf2af53ed 100644
--- a/lib/datasource/nuget/v3.js
+++ b/lib/datasource/nuget/v3.ts
@@ -1,28 +1,26 @@
-const parse = require('github-url-from-git');
-const semver = require('semver');
-const { XmlDocument } = require('xmldoc');
-const { logger } = require('../../logger');
-const got = require('../../util/got');
-
-module.exports = {
-  getQueryUrl,
-  getPkgReleases,
-  getDefaultFeed,
-};
+import parse from 'github-url-from-git';
+import * as semver from 'semver';
+import { XmlDocument } from 'xmldoc';
+import { logger } from '../../logger';
+import got from '../../util/got';
+import { ReleaseResult } from '../common';
 
 // https://api.nuget.org/v3/index.json is a default official nuget feed
 const defaultNugetFeed = 'https://api.nuget.org/v3/index.json';
 const cacheNamespace = 'datasource-nuget';
 
-function getDefaultFeed() {
+export function getDefaultFeed() {
   return defaultNugetFeed;
 }
 
-async function getQueryUrl(url) {
+export async function getQueryUrl(url: string): Promise<string> {
   // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource
   const resourceType = 'SearchQueryService';
   const cacheKey = `${url}:${resourceType}`;
-  const cachedResult = await renovateCache.get(cacheNamespace, cacheKey);
+  const cachedResult = await renovateCache.get<string>(
+    cacheNamespace,
+    cacheKey
+  );
 
   // istanbul ignore if
   if (cachedResult) {
@@ -61,14 +59,19 @@ async function getQueryUrl(url) {
   }
 }
 
-async function getPkgReleases(registryUrl, feedUrl, pkgName) {
+export async function getPkgReleases(
+  registryUrl: string,
+  feedUrl: string,
+  pkgName: string
+): Promise<ReleaseResult> {
   let queryUrl = `${feedUrl}?q=${pkgName}`;
   if (registryUrl.toLowerCase() === defaultNugetFeed.toLowerCase()) {
     queryUrl = queryUrl.replace('q=', 'q=PackageId:');
     queryUrl += '&semVerLevel=2.0.0&prerelease=true';
   }
-  const dep = {
+  const dep: ReleaseResult = {
     pkgName,
+    releases: null,
   };
   try {
     const pkgUrlListRaw = await got(queryUrl, {
@@ -100,7 +103,7 @@ async function getPkgReleases(registryUrl, feedUrl, pkgName) {
         .map(release => semver.valid(release.version))
         .filter(Boolean)
         .filter(version => !semver.prerelease(version));
-      let lastVersion;
+      let lastVersion: string;
       // istanbul ignore else
       if (sanitizedVersions.length) {
         // Use the last stable version we found
@@ -111,7 +114,7 @@ async function getPkgReleases(registryUrl, feedUrl, pkgName) {
       }
       if (registryUrl.toLowerCase() === defaultNugetFeed.toLowerCase()) {
         const nugetOrgApi = `https://api.nuget.org/v3-flatcontainer/${pkgName.toLowerCase()}/${lastVersion}/${pkgName.toLowerCase()}.nuspec`;
-        let metaresult;
+        let metaresult: { body: string };
         try {
           metaresult = await got(nugetOrgApi, { hostType: 'nuget' });
         } catch (err) /* istanbul ignore next */ {
diff --git a/lib/datasource/orb/index.js b/lib/datasource/orb/index.ts
similarity index 70%
rename from lib/datasource/orb/index.js
rename to lib/datasource/orb/index.ts
index 0c912d501f603f1801f40a9ab579134caa41214a..61b399be1c8faa06275531bd0dfcf09d6842e5c8 100644
--- a/lib/datasource/orb/index.js
+++ b/lib/datasource/orb/index.ts
@@ -1,21 +1,29 @@
-const { logger } = require('../../logger');
-const got = require('../../util/got');
+import { logger } from '../../logger';
+import got from '../../util/got';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
-module.exports = {
-  getPkgReleases,
-};
+interface OrbRelease {
+  homeUrl?: string;
+  versions: {
+    version: string;
+  }[];
+}
 
-/*
+/**
  * orb.getPkgReleases
  *
  * This function will fetch an orb from CircleCI and return all semver versions.
  */
-
-async function getPkgReleases({ lookupName }) {
+export async function getPkgReleases({
+  lookupName,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   logger.debug({ lookupName }, 'orb.getPkgReleases()');
   const cacheNamespace = 'orb';
   const cacheKey = lookupName;
-  const cachedResult = await renovateCache.get(cacheNamespace, cacheKey);
+  const cachedResult = await renovateCache.get<ReleaseResult>(
+    cacheNamespace,
+    cacheKey
+  );
   // istanbul ignore if
   if (cachedResult) {
     return cachedResult;
@@ -26,7 +34,7 @@ async function getPkgReleases({ lookupName }) {
     variables: {},
   };
   try {
-    const res = (await got.post(url, {
+    const res: OrbRelease = (await got.post(url, {
       body,
       json: true,
       retry: 5,
@@ -36,17 +44,18 @@ async function getPkgReleases({ lookupName }) {
       return null;
     }
     // Simplify response before caching and returning
-    const dep = {
+    const dep: ReleaseResult = {
       name: lookupName,
       versions: {},
+      releases: null,
     };
     if (res.homeUrl && res.homeUrl.length) {
       dep.homepage = res.homeUrl;
     }
     dep.homepage =
       dep.homepage || `https://circleci.com/orbs/registry/orb/${lookupName}`;
-    dep.releases = res.versions.map(v => v.version);
-    dep.releases = dep.releases.map(version => ({
+    const releases = res.versions.map(v => v.version);
+    dep.releases = releases.map(version => ({
       version,
     }));
     logger.trace({ dep }, 'dep');
diff --git a/lib/datasource/packagist/index.js b/lib/datasource/packagist/index.ts
similarity index 76%
rename from lib/datasource/packagist/index.js
rename to lib/datasource/packagist/index.ts
index 8adeb74eb952cf0250ac2cca759fd0b42df73ac4..019323ed29e0bb51a31aa5eff8f9392a9a491420 100644
--- a/lib/datasource/packagist/index.js
+++ b/lib/datasource/packagist/index.ts
@@ -1,18 +1,17 @@
 import is from '@sindresorhus/is';
 
-const URL = require('url');
-const delay = require('delay');
-const parse = require('github-url-from-git');
-const pAll = require('p-all');
-const { logger } = require('../../logger');
+import URL from 'url';
+import delay from 'delay';
+import parse from 'github-url-from-git';
+import pAll from 'p-all';
+import { logger } from '../../logger';
 
-const got = require('../../util/got');
-const hostRules = require('../../util/host-rules');
+import got from '../../util/got';
+import * as hostRules from '../../util/host-rules';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
-export { getPkgReleases };
-
-function getHostOpts(url) {
-  const opts = {
+function getHostOpts(url: string) {
+  const opts: any = {
     json: true,
   };
   const { username, password } = hostRules.find({ hostType: 'packagist', url });
@@ -22,12 +21,30 @@ function getHostOpts(url) {
   return opts;
 }
 
-async function getRegistryMeta(regUrl) {
+interface PackageMeta {
+  includes?: Record<string, { sha256: string }>;
+  packages: Record<string, RegistryFile>;
+  'provider-includes': Record<string, { sha256: string }>;
+  'providers-url'?: string;
+}
+
+interface RegistryFile {
+  key: string;
+  sha256: string;
+}
+interface RegistryMeta {
+  files?: RegistryFile[];
+  providersUrl?: string;
+  includesFiles?: RegistryFile[];
+  packages?: Record<string, RegistryFile>;
+}
+
+async function getRegistryMeta(regUrl: string) {
   try {
     const url = URL.resolve(regUrl.replace(/\/?$/, '/'), 'packages.json');
     const opts = getHostOpts(url);
-    const res = (await got(url, opts)).body;
-    const meta = {};
+    const res: PackageMeta = (await got(url, opts)).body;
+    const meta: RegistryMeta = {};
     meta.packages = res.packages;
     if (res.includes) {
       meta.includesFiles = [];
@@ -73,7 +90,15 @@ async function getRegistryMeta(regUrl) {
   }
 }
 
-async function getPackagistFile(regUrl, file) {
+interface PackagistFile {
+  providers: Record<string, RegistryFile>;
+  packages?: Record<string, RegistryFile>;
+}
+
+async function getPackagistFile(
+  regUrl: string,
+  file: RegistryFile
+): Promise<PackagistFile> {
   const { key, sha256 } = file;
   const fileName = key.replace('%hash%', sha256);
   const opts = getHostOpts(regUrl);
@@ -99,8 +124,8 @@ async function getPackagistFile(regUrl, file) {
   return res;
 }
 
-function extractDepReleases(versions) {
-  const dep = {};
+function extractDepReleases(versions: RegistryFile): ReleaseResult {
+  const dep: ReleaseResult = { releases: null };
   // istanbul ignore if
   if (!versions) {
     dep.releases = [];
@@ -121,7 +146,15 @@ function extractDepReleases(versions) {
   return dep;
 }
 
-async function getAllPackages(regUrl) {
+interface AllPackages {
+  packages: Record<string, RegistryFile>;
+  providersUrl: string;
+  providerPackages: Record<string, string>;
+
+  includesPackages: Record<string, ReleaseResult>;
+}
+
+async function getAllPackages(regUrl: string): Promise<AllPackages> {
   let repoCacheResult = global.repoCache[`packagist-${regUrl}`];
   // istanbul ignore if
   if (repoCacheResult) {
@@ -138,7 +171,7 @@ async function getAllPackages(regUrl) {
     return null;
   }
   const { packages, providersUrl, files, includesFiles } = registryMeta;
-  const providerPackages = {};
+  const providerPackages: Record<string, string> = {};
   if (files) {
     const queue = files.map(file => () => getPackagistFile(regUrl, file));
     const resolvedFiles = await pAll(queue, { concurrency: 5 });
@@ -148,7 +181,7 @@ async function getAllPackages(regUrl) {
       }
     }
   }
-  const includesPackages = {};
+  const includesPackages: Record<string, ReleaseResult> = {};
   if (includesFiles) {
     for (const file of includesFiles) {
       const res = await getPackagistFile(regUrl, file);
@@ -161,7 +194,7 @@ async function getAllPackages(regUrl) {
       }
     }
   }
-  const allPackages = {
+  const allPackages: AllPackages = {
     packages,
     providersUrl,
     providerPackages,
@@ -171,14 +204,17 @@ async function getAllPackages(regUrl) {
   return allPackages;
 }
 
-async function packagistOrgLookup(name) {
+async function packagistOrgLookup(name: string) {
   const cacheNamespace = 'datasource-packagist-org';
-  const cachedResult = await renovateCache.get(cacheNamespace, name);
+  const cachedResult = await renovateCache.get<ReleaseResult>(
+    cacheNamespace,
+    name
+  );
   // istanbul ignore if
   if (cachedResult) {
     return cachedResult;
   }
-  let dep = null;
+  let dep: ReleaseResult = null;
   const regUrl = 'https://packagist.org';
   const pkgUrl = URL.resolve(regUrl, `/p/${name}.json`);
   const res = (await got(pkgUrl, {
@@ -195,7 +231,7 @@ async function packagistOrgLookup(name) {
   return dep;
 }
 
-async function packageLookup(regUrl, name) {
+async function packageLookup(regUrl: string, name: string) {
   try {
     if (regUrl === 'https://packagist.org') {
       const packagistResult = await packagistOrgLookup(name);
@@ -251,10 +287,13 @@ async function packageLookup(regUrl, name) {
   }
 }
 
-async function getPkgReleases({ lookupName, registryUrls }) {
+export async function getPkgReleases({
+  lookupName,
+  registryUrls,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   logger.trace(`getPkgReleases(${lookupName})`);
 
-  let res;
+  let res: ReleaseResult;
   const registries = is.nonEmptyArray(registryUrls)
     ? registryUrls
     : ['https://packagist.org'];
diff --git a/lib/datasource/pypi/index.js b/lib/datasource/pypi/index.ts
similarity index 73%
rename from lib/datasource/pypi/index.js
rename to lib/datasource/pypi/index.ts
index 825824e3d081c72355ad6958472c91c8f19ca6f4..865332ab486b0892558b8d349fcee0ca5e13bc52 100644
--- a/lib/datasource/pypi/index.js
+++ b/lib/datasource/pypi/index.ts
@@ -1,18 +1,19 @@
 import is from '@sindresorhus/is';
+import url from 'url';
+import { parse } from 'node-html-parser';
+import { logger } from '../../logger';
+import { matches } from '../../versioning/pep440';
+import got from '../../util/got';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
-const url = require('url');
-const { parse } = require('node-html-parser');
-const { logger } = require('../../logger');
-const { matches } = require('../../versioning/pep440');
-const got = require('../../util/got');
-
-export { getPkgReleases };
-
-function normalizeName(input) {
+function normalizeName(input: string) {
   return input.toLowerCase().replace(/(-|\.)/g, '_');
 }
 
-function compatibleVersions(releases, compatibility) {
+function compatibleVersions(
+  releases: Record<string, { requires_python?: boolean }[]>,
+  compatibility: Record<string, string>
+) {
   const versions = Object.keys(releases);
   if (!(compatibility && compatibility.python)) {
     return versions;
@@ -27,11 +28,11 @@ function compatibleVersions(releases, compatibility) {
   );
 }
 
-/**
- *
- * @param {{compatibility:any, lookupName:string, registryUrls?: string[] }} args
- */
-async function getPkgReleases({ compatibility, lookupName, registryUrls }) {
+export async function getPkgReleases({
+  compatibility,
+  lookupName,
+  registryUrls,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   let hostUrls = ['https://pypi.org/pypi/'];
   if (is.nonEmptyArray(registryUrls)) {
     hostUrls = registryUrls;
@@ -41,7 +42,7 @@ async function getPkgReleases({ compatibility, lookupName, registryUrls }) {
   }
   for (let hostUrl of hostUrls) {
     hostUrl += hostUrl.endsWith('/') ? '' : '/';
-    let dep;
+    let dep: ReleaseResult;
     if (hostUrl.endsWith('/simple/')) {
       dep = await getSimpleDependency(lookupName, hostUrl);
     } else {
@@ -54,10 +55,14 @@ async function getPkgReleases({ compatibility, lookupName, registryUrls }) {
   return null;
 }
 
-async function getDependency(depName, hostUrl, compatibility) {
+async function getDependency(
+  depName: string,
+  hostUrl: string,
+  compatibility: Record<string, string>
+) {
   const lookupUrl = url.resolve(hostUrl, `${depName}/json`);
   try {
-    const dependency = {};
+    const dependency: ReleaseResult = { releases: null };
     const rep = await got(url.parse(lookupUrl), {
       json: true,
       hostType: 'pypi',
@@ -103,11 +108,14 @@ async function getDependency(depName, hostUrl, compatibility) {
   }
 }
 
-async function getSimpleDependency(depName, hostUrl) {
+async function getSimpleDependency(
+  depName: string,
+  hostUrl: string
+): Promise<ReleaseResult> {
   const lookupUrl = url.resolve(hostUrl, `${depName}`);
   try {
-    const dependency = {};
-    const response = await got(url.parse(lookupUrl), {
+    const dependency: ReleaseResult = { releases: null };
+    const response: { body: string } = await got(url.parse(lookupUrl), {
       json: false,
       hostType: 'pypi',
     });
@@ -116,11 +124,10 @@ async function getSimpleDependency(depName, hostUrl) {
       logger.debug({ dependency: depName }, 'pip package not found');
       return null;
     }
-    const root = parse(dep);
-    // @ts-ignore
+    const root: HTMLElement = parse(dep) as any;
     const links = root.querySelectorAll('a');
-    const versions = new Set();
-    for (const link of links) {
+    const versions = new Set<string>();
+    for (const link of Array.from(links)) {
       const result = extractVersionFromLinkText(link.text, depName);
       if (result) {
         versions.add(result);
@@ -141,7 +148,7 @@ async function getSimpleDependency(depName, hostUrl) {
   }
 }
 
-function extractVersionFromLinkText(text, depName) {
+function extractVersionFromLinkText(text: string, depName: string) {
   const prefix = `${depName}-`;
   const suffix = '.tar.gz';
   if (!(text.startsWith(prefix) && text.endsWith(suffix))) {
diff --git a/lib/datasource/ruby-version/index.js b/lib/datasource/ruby-version/index.ts
similarity index 73%
rename from lib/datasource/ruby-version/index.js
rename to lib/datasource/ruby-version/index.ts
index cd2507bbb98feb50a3c13f4122805dec7006a5e9..4f0768f74943ba9fe6dd290375491212380ea1c6 100644
--- a/lib/datasource/ruby-version/index.js
+++ b/lib/datasource/ruby-version/index.ts
@@ -1,25 +1,27 @@
-const { parse } = require('node-html-parser');
-const { logger } = require('../../logger');
+import { parse } from 'node-html-parser';
+import { logger } from '../../logger';
 
-const got = require('../../util/got');
-const { isVersion } = require('../../versioning/ruby');
-
-module.exports = {
-  getPkgReleases,
-};
+import got from '../../util/got';
+import { isVersion } from '../../versioning/ruby';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
 const rubyVersionsUrl = 'https://www.ruby-lang.org/en/downloads/releases/';
 
-async function getPkgReleases() {
+export async function getPkgReleases(
+  _config?: PkgReleaseConfig
+): Promise<ReleaseResult> {
   // First check the persistent cache
   const cacheNamespace = 'datasource-ruby-version';
-  const cachedResult = await renovateCache.get(cacheNamespace, 'all');
+  const cachedResult = await renovateCache.get<ReleaseResult>(
+    cacheNamespace,
+    'all'
+  );
   // istanbul ignore if
   if (cachedResult) {
     return cachedResult;
   }
   try {
-    const res = {
+    const res: ReleaseResult = {
       homepage: 'https://www.ruby-lang.org',
       sourceUrl: 'https://github.com/ruby/ruby',
       releases: [],
@@ -29,7 +31,7 @@ async function getPkgReleases() {
     // @ts-ignore
     const rows = root.querySelector('.release-list').querySelectorAll('tr');
     for (const row of rows) {
-      const columns = Array.from(
+      const columns: string[] = Array.from(
         row.querySelectorAll('td').map(td => td.innerHTML)
       );
       if (columns.length) {
diff --git a/lib/datasource/rubygems/errors.js b/lib/datasource/rubygems/errors.ts
similarity index 93%
rename from lib/datasource/rubygems/errors.js
rename to lib/datasource/rubygems/errors.ts
index 4583bee07080d96c9d1084789d90310f4135baac..7c9b7971d88e09a43fa339e9aaf60c39388f9ddb 100644
--- a/lib/datasource/rubygems/errors.js
+++ b/lib/datasource/rubygems/errors.ts
@@ -7,7 +7,7 @@ const REQUEST_TIMEOUT = 408;
 const TOO_MANY_REQUEST = 429;
 const SERVICE_UNAVAILABLE = 503;
 
-module.exports = {
+export {
   UNAUTHORIZED,
   FORBIDDEN,
   NOT_FOUND,
diff --git a/lib/datasource/rubygems/get-rubygems-org.js b/lib/datasource/rubygems/get-rubygems-org.ts
similarity index 83%
rename from lib/datasource/rubygems/get-rubygems-org.js
rename to lib/datasource/rubygems/get-rubygems-org.ts
index 96e2cb0072569622d7aa46a0ac4600af48ac068d..096dc47c4e5611172eb15f6e7641f1613441e35c 100644
--- a/lib/datasource/rubygems/get-rubygems-org.js
+++ b/lib/datasource/rubygems/get-rubygems-org.ts
@@ -1,12 +1,9 @@
-const got = require('../../util/got');
-const { logger } = require('../../logger');
-
-module.exports = {
-  getRubygemsOrgDependency,
-};
+import got from '../../util/got';
+import { logger } from '../../logger';
+import { ReleaseResult } from '../common';
 
 let lastSync = new Date('2000-01-01');
-let packageReleases = Object.create(null); // Because we might need a "constructor" key
+let packageReleases: Record<string, string[]> = Object.create(null); // Because we might need a "constructor" key
 let contentLength = 0;
 
 async function updateRubyGemsVersions() {
@@ -17,7 +14,7 @@ async function updateRubyGemsVersions() {
       range: `bytes=${contentLength}-`,
     },
   };
-  let newLines;
+  let newLines: string;
   try {
     logger.debug('Rubygems: Fetching rubygems.org versions');
     newLines = (await got(url, options)).body;
@@ -33,10 +30,10 @@ async function updateRubyGemsVersions() {
     return;
   }
 
-  function processLine(line) {
-    let split;
-    let pkg;
-    let versions;
+  function processLine(line: string) {
+    let split: string[];
+    let pkg: string;
+    let versions: string;
     try {
       const l = line.trim();
       if (!l.length || l.startsWith('created_at:') || l === '---') {
@@ -87,13 +84,15 @@ async function syncVersions() {
   }
 }
 
-async function getRubygemsOrgDependency(lookupName) {
+export async function getRubygemsOrgDependency(
+  lookupName: string
+): Promise<ReleaseResult> {
   logger.debug(`getRubygemsOrgDependency(${lookupName})`);
   await syncVersions();
   if (!packageReleases[lookupName]) {
     return null;
   }
-  const dep = {
+  const dep: ReleaseResult = {
     name: lookupName,
     releases: packageReleases[lookupName].map(version => ({ version })),
   };
diff --git a/lib/datasource/rubygems/get.js b/lib/datasource/rubygems/get.ts
similarity index 85%
rename from lib/datasource/rubygems/get.js
rename to lib/datasource/rubygems/get.ts
index c51b2d6fb3697435ebb34e3849f2af044f6113e7..ce43de4e4caa2a44bef4b12d545aa5a75416427a 100644
--- a/lib/datasource/rubygems/get.js
+++ b/lib/datasource/rubygems/get.ts
@@ -1,8 +1,9 @@
-const { logger } = require('../../logger');
-const got = require('../../util/got');
-const { maskToken } = require('../../util/mask');
-const retriable = require('./retriable');
-const { UNAUTHORIZED, FORBIDDEN, NOT_FOUND } = require('./errors');
+import { logger } from '../../logger';
+import got from '../../util/got';
+import { maskToken } from '../../util/mask';
+import retriable from './retriable';
+import { UNAUTHORIZED, FORBIDDEN, NOT_FOUND } from './errors';
+import { ReleaseResult } from '../common';
 
 const INFO_PATH = '/api/v1/gems';
 const VERSIONS_PATH = '/api/v1/versions';
@@ -50,7 +51,10 @@ const fetch = async ({ dependency, registry, path }) => {
   return response.body;
 };
 
-const getDependency = async ({ dependency, registry }) => {
+export const getDependency = async ({
+  dependency,
+  registry,
+}): Promise<ReleaseResult> => {
   try {
     const info = await fetch({ dependency, registry, path: INFO_PATH });
     if (!info) {
@@ -95,7 +99,3 @@ const getDependency = async ({ dependency, registry }) => {
     return processError({ err, registry, dependency });
   }
 };
-
-module.exports = {
-  getDependency,
-};
diff --git a/lib/datasource/rubygems/index.js b/lib/datasource/rubygems/index.js
deleted file mode 100644
index a2e4f69f7e97dfafd4133f51159f0d7262889e44..0000000000000000000000000000000000000000
--- a/lib/datasource/rubygems/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const { getPkgReleases } = require('./releases');
-
-module.exports = {
-  getPkgReleases,
-};
diff --git a/lib/datasource/rubygems/index.ts b/lib/datasource/rubygems/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d55467325c9d0463aad8addd43f97e1dad5f9703
--- /dev/null
+++ b/lib/datasource/rubygems/index.ts
@@ -0,0 +1 @@
+export { getPkgReleases } from './releases';
diff --git a/lib/datasource/rubygems/releases.js b/lib/datasource/rubygems/releases.ts
similarity index 56%
rename from lib/datasource/rubygems/releases.js
rename to lib/datasource/rubygems/releases.ts
index f7c8f1cf8905b735999bac45b29d9b562e192e47..34596c224b4ab25096714b6c620aeffe8f5d3c72 100644
--- a/lib/datasource/rubygems/releases.js
+++ b/lib/datasource/rubygems/releases.ts
@@ -1,14 +1,16 @@
 import is from '@sindresorhus/is';
+import { getDependency } from './get';
+import { getRubygemsOrgDependency } from './get-rubygems-org';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
-const { getDependency } = require('./get');
-const { getRubygemsOrgDependency } = require('./get-rubygems-org');
-
-/** @param {{lookupName:string, registryUrls?: string[]}} opt */
-async function getPkgReleases({ lookupName, registryUrls }) {
+export async function getPkgReleases({
+  lookupName,
+  registryUrls,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   const registries = is.nonEmptyArray(registryUrls) ? registryUrls : [];
 
   for (const registry of registries) {
-    let pkg;
+    let pkg: ReleaseResult;
     if (registry.endsWith('rubygems.org')) {
       pkg = await getRubygemsOrgDependency(lookupName);
     } else {
@@ -21,5 +23,3 @@ async function getPkgReleases({ lookupName, registryUrls }) {
 
   return null;
 }
-
-export { getPkgReleases };
diff --git a/lib/datasource/rubygems/retriable.js b/lib/datasource/rubygems/retriable.ts
similarity index 64%
rename from lib/datasource/rubygems/retriable.js
rename to lib/datasource/rubygems/retriable.ts
index 791b9cda724af3a24e80a1e8b6ce929ce0196cb1..4a55692ef7bd53139a084bb6ba75819b797928f6 100644
--- a/lib/datasource/rubygems/retriable.js
+++ b/lib/datasource/rubygems/retriable.ts
@@ -1,11 +1,12 @@
-const { logger } = require('../../logger');
-const {
+import got from 'got';
+import { logger } from '../../logger';
+import {
   UNAUTHORIZED,
   FORBIDDEN,
   REQUEST_TIMEOUT,
   TOO_MANY_REQUEST,
   SERVICE_UNAVAILABLE,
-} = require('./errors');
+} from './errors';
 
 const RETRY_AFTER = 600;
 const NUMBER_OF_RETRIES = 5;
@@ -13,13 +14,14 @@ const NUMBER_OF_RETRIES = 5;
 const getDelayStep = () =>
   parseInt(process.env.RENOVATE_RUBYGEMS_RETRY_DELAY_STEP || '1000', 10);
 
-const toMs = value => value * getDelayStep();
-const getBannedDelay = retryAfter =>
+const toMs = (value: number) => value * getDelayStep();
+const getBannedDelay = (retryAfter: string) =>
   (parseInt(retryAfter, 10) || RETRY_AFTER) + 1;
-const getDefaultDelay = count => (NUMBER_OF_RETRIES * getDelayStep()) / count;
+const getDefaultDelay = (count: number) =>
+  (NUMBER_OF_RETRIES * getDelayStep()) / count;
 
-const getDelayMessage = delay => `Retry in ${delay} seconds.`;
-const getErrorMessage = status => {
+const getDelayMessage = (delay: any) => `Retry in ${delay} seconds.`;
+const getErrorMessage = (status: number) => {
   // istanbul ignore next
   switch (status) {
     case UNAUTHORIZED:
@@ -35,7 +37,13 @@ const getErrorMessage = status => {
   }
 };
 
-module.exports = (numberOfRetries = NUMBER_OF_RETRIES) => (_, err) => {
+// TODO: workaround because got does not export HTTPError, should be moved to `lib/util/got`
+export type HTTPError = InstanceType<got.GotInstance['HTTPError']>;
+
+export default (numberOfRetries = NUMBER_OF_RETRIES): got.RetryFunction => (
+  _?: number,
+  err?: Partial<HTTPError>
+) => {
   if (numberOfRetries === 0) {
     return 0;
   }
diff --git a/lib/datasource/sbt/index.js b/lib/datasource/sbt/index.ts
similarity index 81%
rename from lib/datasource/sbt/index.js
rename to lib/datasource/sbt/index.ts
index 9f8d442dd6dab701beb1fcf6bba5e52f1fe6cd78..9456fd1e6b09d81a25d9ecf399e342ad88351c31 100644
--- a/lib/datasource/sbt/index.js
+++ b/lib/datasource/sbt/index.ts
@@ -1,9 +1,12 @@
-const { compare } = require('../../versioning/maven/compare');
-const { downloadHttpProtocol } = require('../maven/util');
-const { parseIndexDir, SBT_PLUGINS_REPO } = require('./util');
-const { logger } = require('../../logger');
+import { compare } from '../../versioning/maven/compare';
+import { downloadHttpProtocol } from '../maven/util';
+import { parseIndexDir, SBT_PLUGINS_REPO } from './util';
+import { logger } from '../../logger';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
-async function getPkgReleases(config) {
+export async function getPkgReleases(
+  config: PkgReleaseConfig
+): Promise<ReleaseResult> {
   const { lookupName, depType } = config;
 
   const registryUrls =
@@ -17,7 +20,7 @@ async function getPkgReleases(config) {
   const [artifact, scalaVersion] = artifactIdSplit;
 
   const repoRoots = registryUrls.map(x => x.replace(/\/?$/, ''));
-  const searchRoots = [];
+  const searchRoots: string[] = [];
   repoRoots.forEach(repoRoot => {
     // Optimize lookup order
     if (depType === 'plugin') {
@@ -56,12 +59,17 @@ async function getPkgReleases(config) {
   return null;
 }
 
-async function resolvePluginReleases(rootUrl, artifact, scalaVersion) {
+async function resolvePluginReleases(
+  rootUrl: string,
+  artifact: string,
+  scalaVersion: string
+) {
   const searchRoot = `${rootUrl}/${artifact}`;
-  const parse = content => parseIndexDir(content, x => !/^\.+$/.test(x));
+  const parse = (content: string) =>
+    parseIndexDir(content, x => !/^\.+$/.test(x));
   const indexContent = await downloadHttpProtocol(searchRoot, 'sbt');
   if (indexContent) {
-    const releases = [];
+    const releases: string[] = [];
     const scalaVersionItems = parse(indexContent);
     const scalaVersions = scalaVersionItems.map(x => x.replace(/^scala_/, ''));
     const searchVersions =
@@ -91,11 +99,15 @@ async function resolvePluginReleases(rootUrl, artifact, scalaVersion) {
   return resolvePackageReleases(rootUrl, artifact, scalaVersion);
 }
 
-async function resolvePackageReleases(searchRoot, artifact, scalaVersion) {
+async function resolvePackageReleases(
+  searchRoot: string,
+  artifact: string,
+  scalaVersion: string
+): Promise<string[]> {
   const indexContent = await downloadHttpProtocol(searchRoot, 'sbt');
   if (indexContent) {
-    const releases = [];
-    const parseSubdirs = content =>
+    const releases: string[] = [];
+    const parseSubdirs = (content: string) =>
       parseIndexDir(content, x => {
         if (x === artifact) return true;
         if (x.indexOf(`${artifact}_native`) === 0) return false;
@@ -110,7 +122,7 @@ async function resolvePackageReleases(searchRoot, artifact, scalaVersion) {
     ) {
       searchSubdirs = [`${artifact}_${scalaVersion}`];
     }
-    const parseReleases = content =>
+    const parseReleases = (content: string) =>
       parseIndexDir(content, x => !/^\.+$/.test(x));
     for (const searchSubdir of searchSubdirs) {
       const content = await downloadHttpProtocol(
@@ -127,7 +139,3 @@ async function resolvePackageReleases(searchRoot, artifact, scalaVersion) {
 
   return null;
 }
-
-module.exports = {
-  getPkgReleases,
-};
diff --git a/lib/datasource/sbt/util.js b/lib/datasource/sbt/util.js
deleted file mode 100644
index 8fbdb9d9d732dccbee7c32be64908b3ae99a818d..0000000000000000000000000000000000000000
--- a/lib/datasource/sbt/util.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const SBT_PLUGINS_REPO = 'https://dl.bintray.com/sbt/sbt-plugin-releases';
-
-function parseIndexDir(content, filterFn = x => !/^\.+/.test(x)) {
-  const unfiltered = content.match(/(?<=href=['"])[^'"]*(?=\/['"])/g) || [];
-  return unfiltered.filter(filterFn);
-}
-
-module.exports = {
-  parseIndexDir,
-  SBT_PLUGINS_REPO,
-};
diff --git a/lib/datasource/sbt/util.ts b/lib/datasource/sbt/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5a402d0baa8d69337706c17c5f2a3ac56e8ae5c9
--- /dev/null
+++ b/lib/datasource/sbt/util.ts
@@ -0,0 +1,10 @@
+export const SBT_PLUGINS_REPO =
+  'https://dl.bintray.com/sbt/sbt-plugin-releases';
+
+export function parseIndexDir(
+  content: string,
+  filterFn = (x: string) => !/^\.+/.test(x)
+) {
+  const unfiltered = content.match(/(?<=href=['"])[^'"]*(?=\/['"])/g) || [];
+  return unfiltered.filter(filterFn);
+}
diff --git a/lib/datasource/terraform/index.js b/lib/datasource/terraform/index.ts
similarity index 75%
rename from lib/datasource/terraform/index.js
rename to lib/datasource/terraform/index.ts
index 949f035c34667861be4abb9582216893eebabdef..ff884aab5d39f294a0757fc1821efb2ebc3dd823 100644
--- a/lib/datasource/terraform/index.js
+++ b/lib/datasource/terraform/index.ts
@@ -1,14 +1,11 @@
 import is from '@sindresorhus/is';
+import parse from 'github-url-from-git';
+import { logger } from '../../logger';
+import got from '../../util/got';
+import { PkgReleaseConfig, ReleaseResult } from '../common';
 
-const parse = require('github-url-from-git');
-const { logger } = require('../../logger');
-
-const got = require('../../util/got');
-
-export { getPkgReleases };
-
-function getRegistryRepository(lookupName, registryUrls) {
-  let registry;
+function getRegistryRepository(lookupName: string, registryUrls: string[]) {
+  let registry: string;
   const split = lookupName.split('/');
   if (split.length > 3 && split[0].includes('.')) {
     [registry] = split;
@@ -28,15 +25,25 @@ function getRegistryRepository(lookupName, registryUrls) {
   };
 }
 
-/*
+interface TerraformRelease {
+  namespace: string;
+  name: string;
+  provider: string;
+  source?: string;
+  versions: string[];
+}
+
+/**
  * terraform.getPkgReleases
  *
  * This function will fetch a package from the specified Terraform registry and return all semver versions.
  *  - `sourceUrl` is supported of "source" field is set
  *  - `homepage` is set to the Terraform registry's page if it's on the official main registry
  */
-
-async function getPkgReleases({ lookupName, registryUrls }) {
+export async function getPkgReleases({
+  lookupName,
+  registryUrls,
+}: PkgReleaseConfig): Promise<ReleaseResult> {
   const { registry, repository } = getRegistryRepository(
     lookupName,
     registryUrls
@@ -44,13 +51,16 @@ async function getPkgReleases({ lookupName, registryUrls }) {
   logger.debug({ registry, repository }, 'terraform.getDependencies()');
   const cacheNamespace = 'terraform';
   const pkgUrl = `${registry}/v1/modules/${repository}`;
-  const cachedResult = await renovateCache.get(cacheNamespace, pkgUrl);
+  const cachedResult = await renovateCache.get<ReleaseResult>(
+    cacheNamespace,
+    pkgUrl
+  );
   // istanbul ignore if
   if (cachedResult) {
     return cachedResult;
   }
   try {
-    const res = (await got(pkgUrl, {
+    const res: TerraformRelease = (await got(pkgUrl, {
       json: true,
       hostType: 'terraform',
     })).body;
@@ -60,9 +70,10 @@ async function getPkgReleases({ lookupName, registryUrls }) {
       return null;
     }
     // Simplify response before caching and returning
-    const dep = {
+    const dep: ReleaseResult = {
       name: repository,
       versions: {},
+      releases: null,
     };
     if (res.source) {
       dep.sourceUrl = parse(res.source);
diff --git a/package.json b/package.json
index 8f4113ee3b15cec67344a392cb35fc9251cb7446..f299beda225413425ac9ae752dd8eb8474c0eccb 100644
--- a/package.json
+++ b/package.json
@@ -167,15 +167,19 @@
     "@types/convert-hrtime": "2.0.0",
     "@types/fs-extra": "8.0.0",
     "@types/got": "9.6.2",
+    "@types/ini": "1.3.30",
     "@types/jest": "24.0.15",
     "@types/js-yaml": "3.12.1",
     "@types/lodash": "4.14.136",
     "@types/luxon": "1.15.2",
+    "@types/nock": "10.0.3",
     "@types/node": "11.13.18",
     "@types/parse-link-header": "1.0.0",
+    "@types/registry-auth-token": "3.3.0",
     "@types/semver": "6.0.1",
     "@types/shelljs": "0.8.5",
     "@types/tmp": "0.1.0",
+    "@types/validator": "10.11.2",
     "@types/xmldoc": "1.1.4",
     "@typescript-eslint/eslint-plugin": "1.12.0",
     "@typescript-eslint/parser": "1.12.0",
diff --git a/test/config/index.spec.js b/test/config/index.spec.js
index 5b86396fa40bb83352cf99328d52657a59537f3f..1d24ce3ce473635bd07d94955d333d056131cb72 100644
--- a/test/config/index.spec.js
+++ b/test/config/index.spec.js
@@ -5,6 +5,8 @@ const defaultConfig = require('../../lib/config/defaults').getConfig();
 const npm = require('../../lib/datasource/npm');
 const presetDefaults = require('./npm/_fixtures/renovate-config-default.json');
 
+jest.mock('../../lib/datasource/npm');
+
 npm.getPkgReleases = jest.fn(() => ({
   'renovate-config':
     presetDefaults.versions[presetDefaults['dist-tags'].latest][
diff --git a/test/config/presets.spec.js b/test/config/presets.spec.js
index d26792c668489ac5eff766e120d1450e94b55f92..93956e03e2b03467cff59a72b5bf1dd547622f35 100644
--- a/test/config/presets.spec.js
+++ b/test/config/presets.spec.js
@@ -6,6 +6,8 @@ const presetGroup = require('./npm/_fixtures/renovate-config-group.json');
 const presetMonorepo = require('./npm/_fixtures/renovate-config-monorepo.json');
 const presetIkatyang = require('./npm/_fixtures/renovate-config-ikatyang.json');
 
+jest.mock('../../lib/datasource/npm');
+
 npm.getPreset = jest.fn((dep, presetName) => {
   if (dep === 'renovate-config-default') {
     return presetDefaults.versions[presetDefaults['dist-tags'].latest][
diff --git a/test/datasource/__snapshots__/cargo.spec.js.snap b/test/datasource/__snapshots__/cargo.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/cargo.spec.js.snap
rename to test/datasource/__snapshots__/cargo.spec.ts.snap
diff --git a/test/datasource/__snapshots__/dart.spec.js.snap b/test/datasource/__snapshots__/dart.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/dart.spec.js.snap
rename to test/datasource/__snapshots__/dart.spec.ts.snap
diff --git a/test/datasource/__snapshots__/docker.spec.js.snap b/test/datasource/__snapshots__/docker.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/docker.spec.js.snap
rename to test/datasource/__snapshots__/docker.spec.ts.snap
diff --git a/test/datasource/__snapshots__/github.spec.js.snap b/test/datasource/__snapshots__/github.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/github.spec.js.snap
rename to test/datasource/__snapshots__/github.spec.ts.snap
diff --git a/test/datasource/__snapshots__/gitlab.spec.js.snap b/test/datasource/__snapshots__/gitlab.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/gitlab.spec.js.snap
rename to test/datasource/__snapshots__/gitlab.spec.ts.snap
diff --git a/test/datasource/__snapshots__/go.spec.js.snap b/test/datasource/__snapshots__/go.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/go.spec.js.snap
rename to test/datasource/__snapshots__/go.spec.ts.snap
diff --git a/test/datasource/__snapshots__/gradle-version.spec.js.snap b/test/datasource/__snapshots__/gradle-version.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/gradle-version.spec.js.snap
rename to test/datasource/__snapshots__/gradle-version.spec.ts.snap
diff --git a/test/datasource/__snapshots__/hex.spec.js.snap b/test/datasource/__snapshots__/hex.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/hex.spec.js.snap
rename to test/datasource/__snapshots__/hex.spec.ts.snap
diff --git a/test/datasource/__snapshots__/index.spec.js.snap b/test/datasource/__snapshots__/index.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/index.spec.js.snap
rename to test/datasource/__snapshots__/index.spec.ts.snap
diff --git a/test/datasource/__snapshots__/metadata.spec.js.snap b/test/datasource/__snapshots__/metadata.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/metadata.spec.js.snap
rename to test/datasource/__snapshots__/metadata.spec.ts.snap
diff --git a/test/datasource/__snapshots__/nuget.spec.js.snap b/test/datasource/__snapshots__/nuget.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/nuget.spec.js.snap
rename to test/datasource/__snapshots__/nuget.spec.ts.snap
diff --git a/test/datasource/__snapshots__/orb.spec.js.snap b/test/datasource/__snapshots__/orb.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/orb.spec.js.snap
rename to test/datasource/__snapshots__/orb.spec.ts.snap
diff --git a/test/datasource/__snapshots__/packagist.spec.js.snap b/test/datasource/__snapshots__/packagist.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/packagist.spec.js.snap
rename to test/datasource/__snapshots__/packagist.spec.ts.snap
diff --git a/test/datasource/__snapshots__/pypi.spec.js.snap b/test/datasource/__snapshots__/pypi.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/pypi.spec.js.snap
rename to test/datasource/__snapshots__/pypi.spec.ts.snap
diff --git a/test/datasource/__snapshots__/ruby-version.spec.js.snap b/test/datasource/__snapshots__/ruby-version.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/ruby-version.spec.js.snap
rename to test/datasource/__snapshots__/ruby-version.spec.ts.snap
diff --git a/test/datasource/__snapshots__/terraform.spec.js.snap b/test/datasource/__snapshots__/terraform.spec.ts.snap
similarity index 100%
rename from test/datasource/__snapshots__/terraform.spec.js.snap
rename to test/datasource/__snapshots__/terraform.spec.ts.snap
diff --git a/test/datasource/cargo.spec.js b/test/datasource/cargo.spec.ts
similarity index 95%
rename from test/datasource/cargo.spec.js
rename to test/datasource/cargo.spec.ts
index 165217b1032e55e012584a28d391f180c6ad4d61..4c8d93b0e3339ac9263d52b52b46beb08fc0228d 100644
--- a/test/datasource/cargo.spec.js
+++ b/test/datasource/cargo.spec.ts
@@ -1,7 +1,9 @@
-const fs = require('fs');
+import fs from 'fs';
 
-const got = require('../../lib/util/got');
-const { getPkgReleases } = require('../../lib/datasource/cargo');
+import _got from '../../lib/util/got';
+import { getPkgReleases } from '../../lib/datasource/cargo';
+
+const got: any = _got;
 
 const res1 = fs.readFileSync('test/datasource/cargo/_fixtures/libc', 'utf8');
 const res2 = fs.readFileSync(
diff --git a/test/datasource/dart.spec.js b/test/datasource/dart.spec.ts
similarity index 92%
rename from test/datasource/dart.spec.js
rename to test/datasource/dart.spec.ts
index 37a73f825a91e0e48c6470dc4d5f41292f80e24f..e8d828b7aa53465f437b58f80911310c9e00de30 100644
--- a/test/datasource/dart.spec.js
+++ b/test/datasource/dart.spec.ts
@@ -1,8 +1,10 @@
-const fs = require('fs');
-const got = require('../../lib/util/got');
-const { getPkgReleases } = require('../../lib/datasource/dart');
+import fs from 'fs';
+import _got from '../../lib/util/got';
+import { getPkgReleases } from '../../lib/datasource/dart';
 
-const body = JSON.parse(
+const got = _got;
+
+const body: any = JSON.parse(
   fs.readFileSync(
     'test/datasource/dart/_fixtures/shared_preferences.json',
     'utf8'
diff --git a/test/datasource/docker.spec.js b/test/datasource/docker.spec.ts
similarity index 97%
rename from test/datasource/docker.spec.js
rename to test/datasource/docker.spec.ts
index 87a815f7e7f17b5f006521fbf3a1a5b5f93478ed..a3e752b57d28d27ee9ae861c775f4ed82a16f9b7 100644
--- a/test/datasource/docker.spec.js
+++ b/test/datasource/docker.spec.ts
@@ -1,8 +1,10 @@
-const got = require('../../lib/util/got');
-const docker = require('../../lib/datasource/docker');
-const { getPkgReleases } = require('../../lib/datasource');
-/** @type any */
-const hostRules = require('../../lib/util/host-rules');
+import _got from '../../lib/util/got';
+import * as docker from '../../lib/datasource/docker';
+import { getPkgReleases } from '../../lib/datasource';
+import * as _hostRules from '../../lib/util/host-rules';
+
+const got: any = _got;
+const hostRules: any = _hostRules;
 
 jest.mock('../../lib/util/got');
 jest.mock('../../lib/util/host-rules');
diff --git a/test/datasource/git-tags.spec.js b/test/datasource/git-tags.spec.ts
similarity index 90%
rename from test/datasource/git-tags.spec.js
rename to test/datasource/git-tags.spec.ts
index 9288c35b6509c14d35ac4ed939707f2a6d41d28e..7825d7490822106428402387cfdf023479f27a69 100644
--- a/test/datasource/git-tags.spec.js
+++ b/test/datasource/git-tags.spec.ts
@@ -1,8 +1,8 @@
-/** @type any */
-const simpleGit = require('simple-git/promise');
-const { getPkgReleases } = require('../../lib/datasource/git-tags');
+import _simpleGit from 'simple-git/promise';
+import { getPkgReleases } from '../../lib/datasource/git-tags';
 
 jest.mock('simple-git/promise.js');
+const simpleGit: any = _simpleGit;
 
 // const lookupName = 'vapor';
 const lookupName = 'https://github.com/example/example.git';
diff --git a/test/datasource/github.spec.js b/test/datasource/github.spec.ts
similarity index 95%
rename from test/datasource/github.spec.js
rename to test/datasource/github.spec.ts
index 7a98c36064cd93c7d685f22b441fb466d7bd03ae..e467751d86c2a76a33da3a49cc6f77ce8d36625f 100644
--- a/test/datasource/github.spec.js
+++ b/test/datasource/github.spec.ts
@@ -1,16 +1,15 @@
 import { api } from '../../lib/platform/github/gh-got-wrapper';
 
-const datasource = require('../../lib/datasource');
-const github = require('../../lib/datasource/github');
-const got = require('../../lib/util/got');
-const hostRules = require('../../lib/util/host-rules');
+import * as datasource from '../../lib/datasource';
+import * as github from '../../lib/datasource/github';
+import got from '../../lib/util/got';
+import * as hostRules from '../../lib/util/host-rules';
 
 jest.mock('../../lib/platform/github/gh-got-wrapper');
 jest.mock('../../lib/util/got');
 jest.mock('../../lib/util/host-rules');
 
-/** @type any */
-const ghGot = api.get;
+const ghGot: any = api.get;
 
 describe('datasource/github', () => {
   beforeEach(() => global.renovateCache.rmAll());
diff --git a/test/datasource/gitlab.spec.js b/test/datasource/gitlab.spec.ts
similarity index 92%
rename from test/datasource/gitlab.spec.js
rename to test/datasource/gitlab.spec.ts
index 7b7c26dcf1ad1cf6c27acb5b7852ee04aa6cb656..2f088dff5e102026a749e7308df8ce721c87c89c 100644
--- a/test/datasource/gitlab.spec.js
+++ b/test/datasource/gitlab.spec.ts
@@ -1,11 +1,12 @@
-const datasource = require('../../lib/datasource');
-const gitlab = require('../../lib/datasource/gitlab');
-/** @type any */
-const glGot = require('../../lib/platform/gitlab/gl-got-wrapper').api.get;
+import * as datasource from '../../lib/datasource';
+import * as gitlab from '../../lib/datasource/gitlab';
+import { api } from '../../lib/platform/gitlab/gl-got-wrapper';
 
 jest.mock('../../lib/platform/gitlab/gl-got-wrapper');
 jest.mock('../../lib/util/got');
 
+const glGot: any = api.get;
+
 describe('datasource/gitlab', () => {
   beforeEach(() => {
     global.repoCache = {};
diff --git a/test/datasource/go.spec.js b/test/datasource/go.spec.ts
similarity index 95%
rename from test/datasource/go.spec.js
rename to test/datasource/go.spec.ts
index 94795d723631610b7a0452999f216ac8f1bbc52d..2dd6762abf9217df857326a9cfbeee0433199cf8 100644
--- a/test/datasource/go.spec.js
+++ b/test/datasource/go.spec.ts
@@ -1,11 +1,13 @@
-const got = require('../../lib/util/got');
-/** @type any */
-const github = require('../../lib/datasource/github');
-const go = require('../../lib/datasource/go');
+import _got from '../../lib/util/got';
+import * as _github from '../../lib/datasource/github';
+import * as go from '../../lib/datasource/go';
 
 jest.mock('../../lib/util/got');
 jest.mock('../../lib/datasource/github');
 
+const got: any = _got;
+const github: any = _github;
+
 const res1 = `<!DOCTYPE html>
 <html>
 <head>
diff --git a/test/datasource/gradle-version.spec.js b/test/datasource/gradle-version.spec.ts
similarity index 86%
rename from test/datasource/gradle-version.spec.js
rename to test/datasource/gradle-version.spec.ts
index 44206c1af66345e4bdaa6ea29371004fd1972c8a..f30ed7c7ce48e8292eee5e21fd0afdfd28873ad4 100644
--- a/test/datasource/gradle-version.spec.js
+++ b/test/datasource/gradle-version.spec.ts
@@ -1,15 +1,16 @@
-const fs = require('fs');
-const got = require('../../lib/util/got');
-const datasource = require('../../lib/datasource');
+import fs from 'fs';
+import _got from '../../lib/util/got';
+import * as datasource from '../../lib/datasource';
 
 jest.mock('../../lib/util/got');
 
-/** @type any */
-const allResponse = fs.readFileSync(
+const got: any = _got;
+
+const allResponse: any = fs.readFileSync(
   'test/datasource/gradle-wrapper/_fixtures/all.json'
 );
 
-let config = {};
+let config: datasource.PkgReleaseConfig = {};
 
 describe('datasource/gradle', () => {
   describe('getPkgReleases', () => {
diff --git a/test/datasource/hex.spec.js b/test/datasource/hex.spec.ts
similarity index 91%
rename from test/datasource/hex.spec.js
rename to test/datasource/hex.spec.ts
index 7559bb2604362accad5f9d7a82d90f13f0adcb98..cb5aacc3a7a5cd190007902e66cdc92ed84abf38 100644
--- a/test/datasource/hex.spec.js
+++ b/test/datasource/hex.spec.ts
@@ -1,8 +1,10 @@
-const fs = require('fs');
-const got = require('../../lib/util/got');
-/** @type any */
-const hostRules = require('../../lib/util/host-rules');
-const { getPkgReleases } = require('../../lib/datasource/hex');
+import fs from 'fs';
+import _got from '../../lib/util/got';
+import * as _hostRules from '../../lib/util/host-rules';
+import { getPkgReleases } from '../../lib/datasource/hex';
+
+const got: any = _got;
+const hostRules: any = _hostRules;
 
 let res1 = fs.readFileSync(
   'test/datasource/hex/_fixtures/certifi.json',
diff --git a/test/datasource/index.spec.js b/test/datasource/index.spec.ts
similarity index 93%
rename from test/datasource/index.spec.js
rename to test/datasource/index.spec.ts
index a3cf872d54327948a3bffb743b4a68049d050f80..870db99448169d2f18fb5326b95df3724cc0c489 100644
--- a/test/datasource/index.spec.js
+++ b/test/datasource/index.spec.ts
@@ -1,10 +1,11 @@
-const datasource = require('../../lib/datasource');
-/** @type any */
-const npmDatasource = require('../../lib/datasource/npm');
+import * as datasource from '../../lib/datasource';
+import * as _npm from '../../lib/datasource/npm';
 
 jest.mock('../../lib/datasource/docker');
 jest.mock('../../lib/datasource/npm');
 
+const npmDatasource: any = _npm;
+
 describe('datasource/index', () => {
   it('returns if digests are supported', async () => {
     expect(await datasource.supportsDigests({ datasource: 'github' })).toBe(
diff --git a/test/datasource/maven.spec.js b/test/datasource/maven.spec.ts
similarity index 98%
rename from test/datasource/maven.spec.js
rename to test/datasource/maven.spec.ts
index e5fa68071f6821eb929b4c3985bfb51b54f95c60..3d84c79897e9700b8ca2459707108ee1184e5401 100644
--- a/test/datasource/maven.spec.js
+++ b/test/datasource/maven.spec.ts
@@ -1,7 +1,6 @@
-const nock = require('nock');
-const fs = require('fs');
-
-const datasource = require('../../lib/datasource');
+import nock from 'nock';
+import fs from 'fs';
+import * as datasource from '../../lib/datasource';
 
 const MYSQL_VERSIONS = [
   '6.0.5',
diff --git a/test/datasource/metadata.spec.js b/test/datasource/metadata.spec.ts
similarity index 97%
rename from test/datasource/metadata.spec.js
rename to test/datasource/metadata.spec.ts
index 2d8ddaf16a92e97c900c7ab5e22e5e7c21906e49..52967c58ccafa8de7c62cfc7c67ad80129067afa 100644
--- a/test/datasource/metadata.spec.js
+++ b/test/datasource/metadata.spec.ts
@@ -1,4 +1,4 @@
-const { addMetaData } = require('../../lib/datasource/metadata');
+import { addMetaData } from '../../lib/datasource/metadata';
 
 describe('datasource/metadata', () => {
   it('Should do nothing if dep is not specified', () => {
diff --git a/test/datasource/npm/__snapshots__/index.spec.js.snap b/test/datasource/npm/__snapshots__/index.spec.ts.snap
similarity index 100%
rename from test/datasource/npm/__snapshots__/index.spec.js.snap
rename to test/datasource/npm/__snapshots__/index.spec.ts.snap
diff --git a/test/datasource/npm/index.spec.js b/test/datasource/npm/index.spec.ts
similarity index 95%
rename from test/datasource/npm/index.spec.js
rename to test/datasource/npm/index.spec.ts
index d0d7ebf3a1c8b1b4ebb950fa098ca140f6509908..47c0f7a7c84c2becb2c4fffb0f058d4f8451f333 100644
--- a/test/datasource/npm/index.spec.js
+++ b/test/datasource/npm/index.spec.ts
@@ -1,15 +1,21 @@
-const registryAuthToken = require('registry-auth-token');
-const nock = require('nock');
-const moment = require('moment');
-const npm = require('../../../lib/datasource/npm');
+import _registryAuthToken from 'registry-auth-token';
+import nock from 'nock';
+import moment from 'moment';
+import * as npm from '../../../lib/datasource/npm';
 
 jest.mock('registry-auth-token');
 jest.mock('delay');
 
-let npmResponse;
+const registryAuthToken: any = _registryAuthToken;
+let npmResponse: any;
 
-function getRelease(dependency, version) {
-  return dependency.releases.find(release => release.version === version);
+function getRelease(
+  dependency: { releases: { version: string; canBeUnpublished?: boolean }[] },
+  version: string
+) {
+  return dependency.releases.find(
+    (release: { version: string }) => release.version === version
+  );
 }
 
 describe('api/npm', () => {
@@ -166,7 +172,7 @@ describe('api/npm', () => {
     nock('https://registry.npmjs.org')
       .get('/foobar')
       .reply(200, presetPackage);
-    const res = await npm.getPreset('foobar', 'default');
+    const res = await npm.getPreset('foobar');
     expect(res).toMatchSnapshot();
   });
   it('should parse repo url', async () => {
diff --git a/test/datasource/nuget.spec.js b/test/datasource/nuget.spec.ts
similarity index 98%
rename from test/datasource/nuget.spec.js
rename to test/datasource/nuget.spec.ts
index f50944eee8947450c54527a628b8030943f0021b..efca574cca48b3f6586cee81429a34cd06e57bb2 100644
--- a/test/datasource/nuget.spec.js
+++ b/test/datasource/nuget.spec.ts
@@ -1,6 +1,6 @@
-const fs = require('fs');
-const got = require('../../lib/util/got');
-const datasource = require('../../lib/datasource');
+import fs from 'fs';
+import got from '../../lib/util/got';
+import * as datasource from '../../lib/datasource';
 
 jest.mock('../../lib/util/got');
 jest.mock('../../lib/util/host-rules');
diff --git a/test/datasource/orb.spec.js b/test/datasource/orb.spec.ts
similarity index 96%
rename from test/datasource/orb.spec.js
rename to test/datasource/orb.spec.ts
index 18cc716f030eba36a575db786e50471c07772913..4db9ad0bf93cb1ba348a386e09fe77d8210c226f 100644
--- a/test/datasource/orb.spec.js
+++ b/test/datasource/orb.spec.ts
@@ -1,8 +1,10 @@
-const got = require('../../lib/util/got');
-const datasource = require('../../lib/datasource');
+import _got from '../../lib/util/got';
+import * as datasource from '../../lib/datasource';
 
 jest.mock('../../lib/util/got');
 
+const got: any = _got;
+
 const orbData = {
   data: {
     orb: {
diff --git a/test/datasource/packagist.spec.js b/test/datasource/packagist.spec.ts
similarity index 94%
rename from test/datasource/packagist.spec.js
rename to test/datasource/packagist.spec.ts
index 33012d34b352738eb391d6e1105172dad772af65..bd1e968aae11afc152262b040d437b87d7b2e09e 100644
--- a/test/datasource/packagist.spec.js
+++ b/test/datasource/packagist.spec.ts
@@ -1,27 +1,27 @@
-const fs = require('fs');
-const got = require('../../lib/util/got');
-const datasource = require('../../lib/datasource');
-const hostRules = require('../../lib/util/host-rules');
+import fs from 'fs';
+import _got from '../../lib/util/got';
+import * as datasource from '../../lib/datasource';
+import * as _hostRules from '../../lib/util/host-rules';
 
 jest.mock('../../lib/util/got');
 jest.mock('../../lib/util/host-rules');
 
-/** @type any */
-const includesJson = fs.readFileSync(
+const got = _got;
+const hostRules = _hostRules;
+
+const includesJson: any = fs.readFileSync(
   'test/datasource/packagist/_fixtures/includes.json'
 );
-/** @type any */
-const beytJson = fs.readFileSync(
+const beytJson: any = fs.readFileSync(
   'test/datasource/packagist/_fixtures/1beyt.json'
 );
-/** @type any */
-const mailchimpJson = fs.readFileSync(
+const mailchimpJson: any = fs.readFileSync(
   'test/datasource/packagist/_fixtures/mailchimp-api.json'
 );
 
 describe('datasource/packagist', () => {
   describe('getPkgReleases', () => {
-    let config;
+    let config: datasource.PkgReleaseConfig;
     beforeEach(() => {
       jest.resetAllMocks();
       hostRules.find = jest.fn(input => input);
diff --git a/test/datasource/pypi.spec.js b/test/datasource/pypi.spec.ts
similarity index 97%
rename from test/datasource/pypi.spec.js
rename to test/datasource/pypi.spec.ts
index dbb8f1e6642719c4cf3f46768c0af4dd537ecb6f..9c360672797a30e54d0ac3bf161a57b62984203e 100644
--- a/test/datasource/pypi.spec.js
+++ b/test/datasource/pypi.spec.ts
@@ -1,11 +1,10 @@
-const fs = require('fs');
-const got = require('../../lib/util/got');
-const datasource = require('../../lib/datasource');
+import fs from 'fs';
+import got from '../../lib/util/got';
+import * as datasource from '../../lib/datasource';
 
 jest.mock('../../lib/util/got');
 
-/** @type any */
-const res1 = fs.readFileSync(
+const res1: any = fs.readFileSync(
   'test/datasource/pypi/_fixtures/azure-cli-monitor.json'
 );
 const htmlResponse = fs.readFileSync(
diff --git a/test/datasource/ruby-version.spec.js b/test/datasource/ruby-version.spec.ts
similarity index 85%
rename from test/datasource/ruby-version.spec.js
rename to test/datasource/ruby-version.spec.ts
index fee67efab3c99f756b2a0421d43845c39cd07e99..c4235f0e21309f09626e6190d8d9fc3af9f7be23 100644
--- a/test/datasource/ruby-version.spec.js
+++ b/test/datasource/ruby-version.spec.ts
@@ -1,9 +1,11 @@
-const fs = require('fs');
-const got = require('../../lib/util/got');
-const { getPkgReleases } = require('../../lib/datasource/ruby-version');
+import fs from 'fs';
+import _got from '../../lib/util/got';
+import { getPkgReleases } from '../../lib/datasource/ruby-version';
 
 jest.mock('../../lib/util/got');
 
+const got: any = _got;
+
 const rubyReleasesHtml = fs.readFileSync(
   'test/datasource/ruby-version/_fixtures/releases.html',
   'utf8'
diff --git a/test/datasource/rubygems/__snapshots__/index.spec.js.snap b/test/datasource/rubygems/__snapshots__/index.spec.ts.snap
similarity index 100%
rename from test/datasource/rubygems/__snapshots__/index.spec.js.snap
rename to test/datasource/rubygems/__snapshots__/index.spec.ts.snap
diff --git a/test/datasource/rubygems/index.spec.js b/test/datasource/rubygems/index.spec.ts
similarity index 93%
rename from test/datasource/rubygems/index.spec.js
rename to test/datasource/rubygems/index.spec.ts
index 9e61afc139c444f5a35671851b61d2ed6dac2414..ceea2878168efc77f97a0364bbea6d6547ac43ee 100644
--- a/test/datasource/rubygems/index.spec.js
+++ b/test/datasource/rubygems/index.spec.ts
@@ -1,7 +1,7 @@
-const got = require('../../../lib/util/got');
-const railsInfo = require('./_fixtures/rails/info.json');
-const railsVersions = require('./_fixtures/rails/versions.json');
-const rubygems = require('../../../lib/datasource/rubygems/index.js');
+import got from '../../../lib/util/got';
+import railsInfo from './_fixtures/rails/info.json';
+import railsVersions from './_fixtures/rails/versions.json';
+import * as rubygems from '../../../lib/datasource/rubygems';
 
 const rubygemsOrgVersions = `created_at: 2017-03-27T04:38:13+00:00
 ---
diff --git a/test/datasource/rubygems/retriable.spec.js b/test/datasource/rubygems/retriable.spec.ts
similarity index 81%
rename from test/datasource/rubygems/retriable.spec.js
rename to test/datasource/rubygems/retriable.spec.ts
index 27cc770a8f55ad0ccf8bfd752ff39845a652f97d..463fe41477ff5b1f5b832877b07747c6cf1c5216 100644
--- a/test/datasource/rubygems/retriable.spec.js
+++ b/test/datasource/rubygems/retriable.spec.ts
@@ -1,4 +1,4 @@
-const retriable = require('../../../lib/datasource/rubygems/retriable.js');
+import retriable from '../../../lib/datasource/rubygems/retriable';
 
 describe('datasource/rubygems/retriable', () => {
   const { RENOVATE_RUBYGEMS_RETRY_DELAY_STEP } = process.env;
@@ -8,21 +8,21 @@ describe('datasource/rubygems/retriable', () => {
   });
 
   it('returns 0 when numberOfRetries equals 0', () => {
-    expect(retriable(0)()).toEqual(0);
+    expect(retriable(0)(null, null)).toEqual(0);
   });
 
   it('returns retry after header + 1 second if request is banned', () => {
     expect(
       retriable(1)(null, {
         statusCode: 429,
-        headers: { 'retry-after': 5 },
+        headers: { 'retry-after': '5' },
       })
     ).toEqual(6);
 
     expect(
       retriable(1)(null, {
         statusCode: 503,
-        headers: { 'retry-after': 9 },
+        headers: { 'retry-after': '9' },
       })
     ).toEqual(10);
   });
diff --git a/test/datasource/sbt/__snapshots__/index.spec.js.snap b/test/datasource/sbt/__snapshots__/index.spec.ts.snap
similarity index 100%
rename from test/datasource/sbt/__snapshots__/index.spec.js.snap
rename to test/datasource/sbt/__snapshots__/index.spec.ts.snap
diff --git a/test/datasource/sbt/index.spec.js b/test/datasource/sbt/index.spec.ts
similarity index 95%
rename from test/datasource/sbt/index.spec.js
rename to test/datasource/sbt/index.spec.ts
index df354dd29d7fe3e984f70dafbc46b965a3a78cdd..913a4167b323f8c8e79b70ec3f38e3dfd6518a0e 100644
--- a/test/datasource/sbt/index.spec.js
+++ b/test/datasource/sbt/index.spec.ts
@@ -1,14 +1,12 @@
-const path = require('path');
-const fs = require('fs');
-const nock = require('nock');
-
-const { getPkgReleases } = require('../../../lib/datasource/sbt');
-
-const { DEFAULT_MAVEN_REPO } = require('../../../lib/manager/maven/extract');
-const {
+import path from 'path';
+import fs from 'fs';
+import nock from 'nock';
+import { getPkgReleases } from '../../../lib/datasource/sbt';
+import { DEFAULT_MAVEN_REPO } from '../../../lib/manager/maven/extract';
+import {
   parseIndexDir,
   SBT_PLUGINS_REPO,
-} = require('../../../lib/datasource/sbt/util');
+} from '../../../lib/datasource/sbt/util';
 
 const mavenIndexHtml = fs.readFileSync(
   path.resolve(__dirname, `./_fixtures/maven-index.html`),
diff --git a/test/datasource/terraform.spec.js b/test/datasource/terraform.spec.ts
similarity index 92%
rename from test/datasource/terraform.spec.js
rename to test/datasource/terraform.spec.ts
index 247cd121b70120d96ad6880c385d374797bbe9d4..7cb4611edd35f5b4e8904ce281c5e9043b2ac00d 100644
--- a/test/datasource/terraform.spec.js
+++ b/test/datasource/terraform.spec.ts
@@ -1,10 +1,10 @@
-const fs = require('fs');
-const got = require('../../lib/util/got');
-const datasource = require('../../lib/datasource');
+import fs from 'fs';
+import got from '../../lib/util/got';
+import * as datasource from '../../lib/datasource';
 
 jest.mock('../../lib/util/got');
-/** @type any */
-const consulData = fs.readFileSync(
+
+const consulData: any = fs.readFileSync(
   'test/datasource/terraform/_fixtures/registry-consul.json'
 );
 
diff --git a/yarn.lock b/yarn.lock
index b9f252e7ccc80e3c98a6bcf5d61d0ecc4ed46544..c5bbeb120b418ec3254e18a0f17d276d547dd06a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1145,6 +1145,11 @@
     "@types/tough-cookie" "*"
     form-data "^2.5.0"
 
+"@types/ini@1.3.30":
+  version "1.3.30"
+  resolved "https://registry.yarnpkg.com/@types/ini/-/ini-1.3.30.tgz#d1485459c9fad84e937414b832a2adb649eab379"
+  integrity sha512-2+iF8zPSbpU83UKE+PNd4r/MhwNAdyGpk3H+VMgEH3EhjFZq1kouLgRoZrmIcmoGX97xFvqdS44DkICR5Nz3tQ==
+
 "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
@@ -1197,6 +1202,13 @@
   resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
   integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
 
+"@types/nock@10.0.3":
+  version "10.0.3"
+  resolved "https://registry.yarnpkg.com/@types/nock/-/nock-10.0.3.tgz#dab1d18ffbccfbf2db811dab9584304eeb6e1c4c"
+  integrity sha512-OthuN+2FuzfZO3yONJ/QVjKmLEuRagS9TV9lEId+WHL9KhftYG+/2z+pxlr0UgVVXSpVD8woie/3fzQn8ft/Ow==
+  dependencies:
+    "@types/node" "*"
+
 "@types/node@*":
   version "12.6.2"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.2.tgz#a5ccec6abb6060d5f20d256fb03ed743e9774999"
@@ -1217,6 +1229,11 @@
   resolved "https://registry.yarnpkg.com/@types/parse-link-header/-/parse-link-header-1.0.0.tgz#69f059e40a0fa93dc2e095d4142395ae6adc5d7a"
   integrity sha512-fCA3btjE7QFeRLfcD0Sjg+6/CnmC66HpMBoRfRzd2raTaWMJV21CCZ0LO8MOqf8onl5n0EPfjq4zDhbyX8SVwA==
 
+"@types/registry-auth-token@3.3.0":
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/@types/registry-auth-token/-/registry-auth-token-3.3.0.tgz#bfb57ed386d84749c982ec20c804ac119382b285"
+  integrity sha512-HEnnGNRFbVXwqLV1xzQTY4zElLEn85mHAXm9LbAut0+gQI6LafAhW0qmCLuBcm5QtekXQWXFGchi0ZjTdX6Upw==
+
 "@types/retry@^0.12.0":
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
@@ -1250,6 +1267,11 @@
   resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d"
   integrity sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==
 
+"@types/validator@10.11.2":
+  version "10.11.2"
+  resolved "https://registry.yarnpkg.com/@types/validator/-/validator-10.11.2.tgz#48b60ca2cca927081f37a1ad1de3e25d04abc9f0"
+  integrity sha512-k/ju1RsdP5ACFUWebqsyEy0avP5uNJCs2p3pmTHzOZdd4gMSAJTq7iUEHFY3tt3emBrPTm6oGvfZ4SzcqOgLPQ==
+
 "@types/xmldoc@1.1.4":
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/@types/xmldoc/-/xmldoc-1.1.4.tgz#5867d4e29739719c633bf16413c5a4a4c1c3c802"