diff --git a/lib/compiler-finder.js b/lib/compiler-finder.ts
similarity index 87%
rename from lib/compiler-finder.js
rename to lib/compiler-finder.ts
index 48f62d81de752e73a4c9bc86e82d1f31db94aa4e..b4f068b4264905255736a5adc04caa3f8d388e25 100644
--- a/lib/compiler-finder.js
+++ b/lib/compiler-finder.ts
@@ -33,21 +33,48 @@ import urljoin from 'url-join';
 
 import {InstanceFetcher} from './aws';
 import {logger} from './logger';
+import {PropertyGetter, PropertyValue, Widen} from './properties.interfaces';
+import {CompilerProps, RawPropertiesGetter} from './properties';
+import AWS from 'aws-sdk';
+import {ClientOptionsHandler} from './options-handler';
+import {CompileHandler} from './handlers/compile';
 
 const sleep = promisify(setTimeout);
 
+export type CompilerFinderArguments = {
+    rootDir: string;
+    env: string[];
+    hostname: string[];
+    port: number;
+    gitReleaseName: string;
+    releaseBuildNumber: string;
+    wantedLanguages: string | null;
+    doCache: boolean;
+    fetchCompilersFromRemote: boolean;
+    ensureNoCompilerClash: boolean;
+    suppressConsoleLog: boolean;
+};
+
 /***
  * Finds and initializes the compilers stored on the properties files
  */
 export class CompilerFinder {
-    /***
-     * @param {CompileHandler} compileHandler
-     * @param {CompilerProps} compilerProps
-     * @param {propsFor} awsProps
-     * @param {Object} args
-     * @param {Object} optionsHandler
-     */
-    constructor(compileHandler, compilerProps, awsProps, args, optionsHandler) {
+    compilerProps: CompilerProps['get'];
+    ceProps: PropertyGetter;
+    awsProps: PropertyGetter;
+    args: CompilerFinderArguments;
+    compileHandler: CompileHandler;
+    languages: Record<string, any>;
+    awsPoller: InstanceFetcher | null = null;
+    optionsHandler: ClientOptionsHandler;
+
+    constructor(
+        compileHandler: CompileHandler,
+        compilerProps: CompilerProps,
+        awsProps: PropertyGetter,
+        args: CompilerFinderArguments,
+        optionsHandler: ClientOptionsHandler,
+    ) {
         this.compilerProps = compilerProps.get.bind(compilerProps);
         this.ceProps = compilerProps.ceProps;
         this.awsProps = awsProps;
@@ -95,7 +122,7 @@ export class CompilerFinder {
                                             `${uriSchema}://${host}:${port}${apiPath}\n` +
                                             `Status Code: ${statusCode}`,
                                     );
-                                } else if (!/^application\/json/.test(contentType)) {
+                                } else if (!contentType || !/^application\/json/.test(contentType)) {
                                     error = new Error(
                                         'Invalid content-type.\n' +
                                             `Expected application/json but received ${contentType}`,
@@ -129,7 +156,7 @@ export class CompilerFinder {
                                             return compiler;
                                         });
                                         resolve(compilers);
-                                    } catch (e) {
+                                    } catch (e: any) {
                                         logger.error(`Error parsing response from ${uri} '${str}': ${e.message}`);
                                         reject(e);
                                     }
@@ -154,7 +181,7 @@ export class CompilerFinder {
         logger.info('Fetching instances from AWS');
         const instances = await this.awsInstances();
         return Promise.all(
-            instances.map(instance => {
+            (instances.filter(instance => instance !== undefined) as AWS.EC2.Instance[]).map(instance => {
                 logger.info('Checking instance ' + instance.InstanceId);
                 const address = this.awsProps('externalTestMode', false)
                     ? instance.PublicDnsName
@@ -164,13 +191,16 @@ export class CompilerFinder {
         );
     }
 
-    async compilerConfigFor(langId, compilerId, parentProps) {
+    async compilerConfigFor(langId: string, compilerId: string, parentProps: RawPropertiesGetter) {
         const base = `compiler.${compilerId}.`;
 
-        function props(propName, def) {
+        function props(propName: string, defaultValue: undefined): PropertyValue;
+        function props<T extends PropertyValue>(propName: string, defaultValue: Widen<T>): typeof defaultValue;
+        function props<T extends PropertyValue>(propName: string, defaultValue?: unknown): T;
+        function props(propName: string, defaultValue?: unknown) {
             const propsForCompiler = parentProps(langId, base + propName);
             if (propsForCompiler !== undefined) return propsForCompiler;
-            return parentProps(langId, propName, def);
+            return parentProps(langId, propName, defaultValue);
         }
 
         const ceToolsPath = props('ceToolsPath', './');
@@ -206,7 +236,7 @@ export class CompilerFinder {
             if (envVarsString === '') {
                 return [];
             }
-            const arr = [];
+            const arr: [string, string][] = [];
             for (const el of envVarsString.split(':')) {
                 const [env, setting] = el.split('=');
                 arr.push([env, setting]);
@@ -261,7 +291,7 @@ export class CompilerFinder {
             notification: props('notification', ''),
             isSemVer: isSemVer,
             semver: semverVer,
-            libsArr: this.getSupportedLibrariesArr(props, langId),
+            libsArr: this.getSupportedLibrariesArr(props),
             tools: _.omit(this.optionsHandler.get().tools[langId], tool => tool.isCompilerExcluded(compilerId, props)),
             unwiseOptions: props('unwiseOptions', '').split('|'),
             hidden: props('hidden', false),
@@ -319,7 +349,10 @@ export class CompilerFinder {
                 }
                 return this.compilerProps(langId, `group.${groupName}.${name}`, parentProps(langId, name, def));
             };
-            const exes = _.compact(this.compilerProps(langId, `group.${groupName}.compilers`, '').split(':'));
+            // TODO: Eliminate this cast
+            const exes = _.compact(
+                (this.compilerProps(langId, `group.${groupName}.compilers`, '') as string).split(':'),
+            );
             logger.debug(`Processing compilers from group ${groupName}`);
             return Promise.all(exes.map(compiler => this.recurseGetCompilers(langId, compiler, props)));
         }
@@ -328,15 +361,15 @@ export class CompilerFinder {
     }
 
     async getCompilers() {
-        const compilers = [];
+        const compilers: any[] = [];
         _.each(this.getExes(), (exs, langId) => {
             _.each(exs, exe => compilers.push(this.recurseGetCompilers(langId, exe, this.compilerProps)));
         });
         return Promise.all(compilers);
     }
 
-    ensureDistinct(compilers) {
-        const ids = {};
+    ensureDistinct(compilers: any[]) {
+        const ids: Record<string, any> = {};
         let foundClash = false;
         _.each(compilers, compiler => {
             if (!ids[compiler.id]) ids[compiler.id] = [];
@@ -372,14 +405,20 @@ export class CompilerFinder {
     }
 
     getExes() {
-        const langToCompilers = this.compilerProps(this.languages, 'compilers', '', exs => _.compact(exs.split(':')));
+        // TODO: Fix typing here
+        const langToCompilers = this.compilerProps(
+            this.languages,
+            'compilers',
+            '',
+            exs => _.compact((exs as string).split(':')) as unknown as PropertyValue,
+        ) as _.Dictionary<any>;
         this.addNdkExes(langToCompilers);
         logger.info('Exes found:', langToCompilers);
         return langToCompilers;
     }
 
     addNdkExes(langToCompilers) {
-        const ndkPaths = this.compilerProps(this.languages, 'androidNdk');
+        const ndkPaths = this.compilerProps(this.languages, 'androidNdk') as _.Dictionary<any>;
         _.each(ndkPaths, (ndkPath, langId) => {
             if (ndkPath) {
                 const toolchains = fs.readdirSync(`${ndkPath}/toolchains`);
diff --git a/lib/properties.ts b/lib/properties.ts
index 3075e2cdd4a4ec446844f2c255f98b4a731f1f85..d019f4556708a4c62a0529b78897cd3e68d56ea4 100644
--- a/lib/properties.ts
+++ b/lib/properties.ts
@@ -67,6 +67,8 @@ export function get(base: string, property: string, defaultValue?: unknown): unk
     return result;
 }
 
+export type RawPropertiesGetter = typeof get;
+
 export function parseProperties(blob, name) {
     const props = {};
     for (const [index, lineOrig] of blob.split('\n').entries()) {
@@ -132,9 +134,9 @@ type LanguageDef = {
  * Compiler property fetcher
  */
 export class CompilerProps {
-    private languages: Record<string, any>;
-    private propsByLangId: Record<string, PropertyGetter>;
-    private ceProps: any;
+    public readonly languages: Record<string, any>;
+    public readonly propsByLangId: Record<string, PropertyGetter>;
+    public readonly ceProps: any;
 
     /***
      * Creates a CompilerProps lookup function
@@ -171,9 +173,9 @@ export class CompilerProps {
      * @returns {*} Transformed value(s) found or fn(defaultValue)
      */
     get(
-        langs: string | LanguageDef[],
+        langs: string | LanguageDef[] | Record<string, any>,
         key: string,
-        defaultValue: PropertyValue,
+        defaultValue?: PropertyValue,
         fn: (item: PropertyValue, language?: any) => PropertyValue = _.identity,
     ) {
         fn = fn || _.identity;