Skip to content

Commit

Permalink
Refactor: eliminate TypeScript "as" keyword (#573)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmercm authored Aug 18, 2023
1 parent 51cb6fc commit a0636ac
Show file tree
Hide file tree
Showing 24 changed files with 122 additions and 71 deletions.
8 changes: 5 additions & 3 deletions src/console/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default class Logger {

isTTY(): boolean {
if (this.stream instanceof WriteStream) {
return (this.stream as WriteStream).isTTY;
return (this.stream satisfies WriteStream).isTTY;
}
if (this.stream instanceof PassThrough) {
// Testing streams should be treated as TTY
Expand All @@ -66,14 +66,16 @@ export default class Logger {
return message;
}

const chalkFuncs: { [key: number]: (message: string) => string } = {
const chalkFuncs = {
[LogLevel.TRACE]: chalk.grey,
[LogLevel.DEBUG]: chalk.magenta,
[LogLevel.INFO]: chalk.cyan,
[LogLevel.WARN]: chalk.yellow,
[LogLevel.ERROR]: chalk.red,
[LogLevel.NOTICE]: chalk.bold,
};
[LogLevel.ALWAYS]: (msg) => msg,
[LogLevel.NEVER]: (msg) => msg,
} satisfies { [key in LogLevel]: (message: string) => string };
const chalkFunc = chalkFuncs[logLevel];

const loggerTime = this.logLevel <= LogLevel.TRACE ? `[${moment().format('HH:mm:ss.SSS')}] ` : '';
Expand Down
6 changes: 3 additions & 3 deletions src/console/singleBarFormatted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ export default class SingleBarFormatted {
: 0;
const incompleteSize = barSize - inProgressSize - completeSize;

return (SingleBarFormatted.BAR_COMPLETE_CHAR || '').repeat(Math.max(completeSize, 0))
+ (SingleBarFormatted.BAR_IN_PROGRESS_CHAR || '').repeat(Math.max(inProgressSize, 0))
+ (SingleBarFormatted.BAR_INCOMPLETE_CHAR || '').repeat(Math.max(incompleteSize, 0));
return SingleBarFormatted.BAR_COMPLETE_CHAR.repeat(Math.max(completeSize, 0))
+ SingleBarFormatted.BAR_IN_PROGRESS_CHAR.repeat(Math.max(inProgressSize, 0))
+ SingleBarFormatted.BAR_INCOMPLETE_CHAR.repeat(Math.max(incompleteSize, 0));
}

private getEtaFormatted(etaSeconds: number): string {
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default class Constants {

static readonly COMMAND_VERSION = PACKAGE_JSON.version;

static readonly ENGINES_NODE = PACKAGE_JSON.engines.node || '*';
static readonly ENGINES_NODE = PACKAGE_JSON.engines?.node ?? '*';

static readonly GLOBAL_TEMP_DIR = GLOBAL_TEMP_DIR;

Expand Down
5 changes: 3 additions & 2 deletions src/igir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import ReportGenerator from './modules/reportGenerator.js';
import ROMHeaderProcessor from './modules/romHeaderProcessor.js';
import ROMScanner from './modules/romScanner.js';
import StatusGenerator from './modules/statusGenerator.js';
import ArrayPoly from './polyfill/arrayPoly.js';
import DATStatus from './types/datStatus.js';
import File from './types/files/file.js';
import DAT from './types/logiqx/dat.js';
Expand Down Expand Up @@ -218,7 +219,7 @@ export default class Igir {
romWithFiles.getRom(),
romWithFiles.getInputFile(),
)))))
.filter((outputDir, idx, outputDirs) => outputDirs.indexOf(outputDir) === idx);
.filter(ArrayPoly.filterUnique);
}

private async deleteMovedRoms(
Expand Down Expand Up @@ -246,7 +247,7 @@ export default class Igir {
}

const progressBar = await this.logger.addProgressBar('Cleaning output directory');
const uniqueDirsToClean = dirsToClean.filter((dir, idx, dirs) => dirs.indexOf(dir) === idx);
const uniqueDirsToClean = dirsToClean.filter(ArrayPoly.filterUnique);
const writtenFilesToExclude = [...datsToWrittenRoms.values()]
.flatMap((parentsToFiles) => [...parentsToFiles.values()])
.flatMap((files) => files);
Expand Down
16 changes: 8 additions & 8 deletions src/modules/candidateGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'path';

import ProgressBar, { ProgressBarSymbol } from '../console/progressBar.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import fsPoly from '../polyfill/fsPoly.js';
import Archive from '../types/files/archives/archive.js';
import ArchiveEntry from '../types/files/archives/archiveEntry.js';
Expand Down Expand Up @@ -156,11 +157,11 @@ export default class CandidateGenerator extends Module {
return [rom, undefined];
}
}),
) as [ROM, ROMWithFiles | undefined][];
) satisfies [ROM, ROMWithFiles | undefined][];

const foundRomsWithFiles = romFiles
.filter(([, romWithFiles]) => romWithFiles)
.map(([, romWithFiles]) => romWithFiles) as ROMWithFiles[];
.map(([, romWithFiles]) => romWithFiles)
.filter(ArrayPoly.filterNotNullish);
const missingRoms = romFiles
.filter(([, romWithFiles]) => !romWithFiles)
.map(([rom]) => rom);
Expand Down Expand Up @@ -188,7 +189,7 @@ export default class CandidateGenerator extends Module {
let romsAndInputFiles = game.getRoms().map((rom) => ([
rom,
(hashCodeToInputFiles.get(rom.hashCode()) ?? []),
])) as [ROM, File[]][];
])) satisfies [ROM, File[]][];

// Detect if there is one input archive that contains every ROM, and prefer to use its entries.
// If we don't do this, here are two situations that can happen:
Expand All @@ -211,7 +212,7 @@ export default class CandidateGenerator extends Module {
roms.push(rom);
// We need to filter out duplicate ROMs because of Games that contain duplicate ROMs, e.g.
// optical media games that have the same track multiple times.
const uniqueRoms = roms.filter((val, idx, values) => values.indexOf(val) === idx);
const uniqueRoms = roms.filter(ArrayPoly.filterUnique);
map.set(archive, uniqueRoms);
});
return map;
Expand Down Expand Up @@ -317,8 +318,7 @@ export default class CandidateGenerator extends Module {
.filter((outputFile) => !(outputFile instanceof ArchiveEntry))
.map((outputFile) => outputFile.getFilePath())
.filter((outputPath, idx, outputPaths) => outputPaths.indexOf(outputPath) !== idx)
.filter((duplicatePath, idx, duplicatePaths) => duplicatePaths
.indexOf(duplicatePath) === idx)
.filter(ArrayPoly.filterUnique)
.sort();
if (!duplicateOutputPaths.length) {
// There are no duplicate non-archive output file paths
Expand All @@ -336,7 +336,7 @@ export default class CandidateGenerator extends Module {
const conflictedInputFiles = romsWithFiles
.filter((romWithFiles) => romWithFiles.getOutputFile().getFilePath() === duplicateOutput)
.map((romWithFiles) => romWithFiles.getInputFile().toString())
.filter((inputFile, idx, inputFiles) => inputFiles.indexOf(inputFile) === idx);
.filter(ArrayPoly.filterUnique);
if (conflictedInputFiles.length > 1) {
hasConflict = true;
let message = `Cannot ${this.options.writeString()} different files to: ${duplicateOutput}:`;
Expand Down
3 changes: 2 additions & 1 deletion src/modules/candidatePatchGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'path';

import ProgressBar, { ProgressBarSymbol } from '../console/progressBar.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import ArchiveEntry from '../types/files/archives/archiveEntry.js';
import File from '../types/files/file.js';
import DAT from '../types/logiqx/dat.js';
Expand Down Expand Up @@ -108,7 +109,7 @@ export default class CandidatePatchGenerator extends Module {
const releaseCandidatePatches = unpatchedReleaseCandidate.getRomsWithFiles()
.map((romWithFiles) => crcToPatches.get(romWithFiles.getInputFile().getCrc32()))
.flatMap((patches) => patches)
.filter((patch) => patch) as Patch[];
.filter(ArrayPoly.filterNotNullish);

// No relevant patches found, no new candidates generated
if (!releaseCandidatePatches.length) {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/candidateWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export default class CandidateWriter extends Module {
.map((romWithFiles) => [
romWithFiles.getInputFile(),
romWithFiles.getOutputFile() as ArchiveEntry<Zip>,
]) as [File, ArchiveEntry<Zip>][];
]) satisfies [File, ArchiveEntry<Zip>][];
if (!inputToOutputZipEntries.length) {
this.progressBar.logTrace(`${dat.getNameShort()}: ${releaseCandidate.getName()}: no zip archives to write`);
return;
Expand Down
3 changes: 2 additions & 1 deletion src/modules/datScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import xml2js from 'xml2js';

import ProgressBar, { ProgressBarSymbol } from '../console/progressBar.js';
import Constants from '../constants.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import bufferPoly from '../polyfill/bufferPoly.js';
import fsPoly from '../polyfill/fsPoly.js';
import File from '../types/files/file.js';
Expand Down Expand Up @@ -102,7 +103,7 @@ export default class DATScanner extends Scanner {
this.progressBar.removeWaitingMessage(waitingMessage);
return callback(null, dat);
},
)).filter((xmlObject) => xmlObject) as DAT[];
)).filter(ArrayPoly.filterNotNullish);

return results
.filter((dat) => {
Expand Down
3 changes: 2 additions & 1 deletion src/modules/directoryCleaner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import util from 'util';

import ProgressBar, { ProgressBarSymbol } from '../console/progressBar.js';
import Constants from '../constants.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import fsPoly from '../polyfill/fsPoly.js';
import File from '../types/files/file.js';
import Options from '../types/options.js';
Expand Down Expand Up @@ -90,7 +91,7 @@ export default class DirectoryCleaner extends Module {
dirsToClean.map(async (dirToClean) => DirectoryCleaner.getEmptyDirs(dirToClean)),
))
.flatMap((emptyDirs) => emptyDirs)
.filter((emptyDir, idx, emptyDirs) => emptyDirs.indexOf(emptyDir) === idx);
.filter(ArrayPoly.filterUnique);
}

// Find all subdirectories and files in the directory
Expand Down
8 changes: 1 addition & 7 deletions src/modules/fileIndexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,7 @@ export default class FileIndexer extends Module {
}

private static setFileInMap<K>(map: Map<K, File[]>, key: K, file: File): void {
if (!map.has(key)) {
map.set(key, [file]);
return;
}

const existing = map.get(key) as File[];
map.set(key, [...existing, file]);
map.set(key, [...(map.get(key) ?? []), file]);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/modules/movedRomDeleter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ProgressBar, { ProgressBarSymbol } from '../console/progressBar.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import fsPoly from '../polyfill/fsPoly.js';
import ArchiveEntry from '../types/files/archives/archiveEntry.js';
import File from '../types/files/file.js';
Expand Down Expand Up @@ -84,7 +85,7 @@ export default class MovedROMDeleter extends Module {

return filePath;
})
.filter((filePath) => filePath) as string[];
.filter(ArrayPoly.filterNotNullish);
}

private static groupFilesByFilePath(files: File[]): Map<string, File[]> {
Expand Down
5 changes: 3 additions & 2 deletions src/modules/patchScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import async, { AsyncResultCallback } from 'async';

import ProgressBar, { ProgressBarSymbol } from '../console/progressBar.js';
import Constants from '../constants.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import File from '../types/files/file.js';
import Options from '../types/options.js';
import Patch from '../types/patches/patch.js';
Expand Down Expand Up @@ -33,7 +34,7 @@ export default class PatchScanner extends Scanner {
const patches = (await async.mapLimit(
files,
Constants.PATCH_SCANNER_THREADS,
async (file, callback: AsyncResultCallback<Patch, Error>) => {
async (file, callback: AsyncResultCallback<Patch | undefined, Error>) => {
await this.progressBar.incrementProgress();
const waitingMessage = `${file.toString()} ...`;
this.progressBar.addWaitingMessage(waitingMessage);
Expand All @@ -49,7 +50,7 @@ export default class PatchScanner extends Scanner {
this.progressBar.removeWaitingMessage(waitingMessage);
}
},
)).filter((patch) => patch);
)).filter(ArrayPoly.filterNotNullish);

this.progressBar.logInfo('done scanning patch files');
return patches;
Expand Down
6 changes: 3 additions & 3 deletions src/modules/reportGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import fs from 'fs';
import util from 'util';

import ProgressBar from '../console/progressBar.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import DATStatus, { Status } from '../types/datStatus.js';
import Options from '../types/options.js';
import ReleaseCandidate from '../types/releaseCandidate.js';
import Module from './module.js';

/**
Expand Down Expand Up @@ -46,7 +46,7 @@ export default class ReportGenerator extends Module {

const releaseCandidates = datStatuses
.flatMap((datStatus) => datStatus.getReleaseCandidates())
.filter((releaseCandidate) => releaseCandidate) as ReleaseCandidate[];
.filter(ArrayPoly.filterNotNullish);
const matchedFiles = releaseCandidates
.flatMap((releaseCandidate) => releaseCandidate.getRomsWithFiles())
.map((romWithFiles) => romWithFiles.getInputFile().getFilePath())
Expand All @@ -55,7 +55,7 @@ export default class ReportGenerator extends Module {
return map;
}, new Map<string, boolean>());
const unmatchedFiles = scannedRomFiles
.filter((filePath, idx, filePaths) => filePaths.indexOf(filePath) === idx)
.filter(ArrayPoly.filterUnique)
.filter((inputFile) => !matchedFiles.has(inputFile))
.sort();
const unmatchedCsv = await DATStatus.filesToCsv(unmatchedFiles, Status.UNMATCHED);
Expand Down
30 changes: 30 additions & 0 deletions src/polyfill/arrayPoly.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export default class ArrayPoly {
/**
* Filter out nullish values from an array, in a way that TypeScript can understand how the
* resulting element type has changed. For example, TypeScript (as of v5.1.3) will tell you that:
*
* <code>
* [1, 2, undefined, 4, undefined].filter((val) => val);
* </code
*
* has the resulting type `(number | undefined)[]`. Instead, use:
*
* <code>
* [1, 2, undefined, 4, undefined].filter(ArrayPoly.filterNotNullish);
* </code>
*/
public static filterNotNullish<T>(value: T | null | undefined): value is T {
return value !== null && value !== undefined;
}

/**
* Filter elements in an array to only unique ones. Usage:
*
* <code>
* [1, 2, 3, 1, 1, 3].filter(ArrayPoly.filterUnique);
* </code>
*/
public static filterUnique<T>(value: T, index: number, array: T[]): boolean {
return array.indexOf(value) === index;
}
}
19 changes: 10 additions & 9 deletions src/types/datStatus.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { writeToString } from '@fast-csv/format';
import chalk, { ChalkInstance } from 'chalk';

import ArrayPoly from '../polyfill/arrayPoly.js';
import DAT from './logiqx/dat.js';
import Game from './logiqx/game.js';
import Parent from './logiqx/parent.js';
Expand Down Expand Up @@ -91,7 +92,7 @@ export default class DATStatus {
}

private static append<T>(map: Map<ROMType, T[]>, romType: ROMType, val: T): void {
const arr = (map.has(romType) ? map.get(romType) : []) as T[];
const arr = map.get(romType) ?? [];
arr.push(val);
map.set(romType, arr);
}
Expand All @@ -109,7 +110,7 @@ export default class DATStatus {
return DATStatus.getAllowedTypes(options)
.reduce((result, romType) => {
const foundReleaseCandidates = (
this.foundRomTypesToReleaseCandidates.get(romType) as ReleaseCandidate[] || []).length;
this.foundRomTypesToReleaseCandidates.get(romType) ?? []).length;
return result || foundReleaseCandidates > 0;
}, false);
}
Expand Down Expand Up @@ -159,7 +160,7 @@ export default class DATStatus {
);

const rows = DATStatus.getValuesForAllowedTypes(options, this.allRomTypesToGames)
.filter((game, idx, games) => games.indexOf(game) === idx)
.filter(ArrayPoly.filterUnique)
.sort((a, b) => a.getName().localeCompare(b.getName()))
.map((game) => {
const releaseCandidate = found.find((rc) => rc && rc.getGame().equals(game));
Expand All @@ -168,12 +169,12 @@ export default class DATStatus {
game.getName(),
releaseCandidate || !game.getRoms().length ? Status.FOUND : Status.MISSING,
releaseCandidate
? (releaseCandidate as ReleaseCandidate).getRomsWithFiles()
? releaseCandidate.getRomsWithFiles()
.map((romWithFiles) => (options.shouldWrite()
? romWithFiles.getOutputFile()
: romWithFiles.getInputFile()))
.map((file) => file.getFilePath())
.filter((filePath, idx, filePaths) => filePaths.indexOf(filePath) === idx)
.filter(ArrayPoly.filterUnique)
: [],
releaseCandidate?.isPatched() ?? false,
game.isBios(),
Expand Down Expand Up @@ -264,9 +265,9 @@ export default class DATStatus {
return DATStatus.getAllowedTypes(options)
.map((type) => romTypesToValues.get(type))
.flatMap((values) => values)
.filter((value) => value)
.filter((value, idx, values) => values.indexOf(value) === idx)
.sort() as T[];
.filter(ArrayPoly.filterNotNullish)
.filter(ArrayPoly.filterUnique)
.sort();
}

private static getAllowedTypes(options: Options): ROMType[] {
Expand All @@ -277,6 +278,6 @@ export default class DATStatus {
!options.getNoDevice() && !options.getOnlyBios() ? ROMType.DEVICE : undefined,
options.getOnlyRetail() || !options.getOnlyBios() ? ROMType.RETAIL : undefined,
ROMType.PATCHED,
].filter((romType) => romType) as ROMType[];
].filter(ArrayPoly.filterNotNullish);
}
}
Loading

0 comments on commit a0636ac

Please sign in to comment.