Enable Typescript strict mode (#426)

This commit is contained in:
Michael Telatynski 2022-10-13 12:42:33 +01:00 committed by GitHub
parent d0c7e3e24b
commit d0e1596bf2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 37 additions and 33 deletions

View file

@ -30,8 +30,9 @@ module.exports = {
"prefer-promise-reject-errors": "off", "prefer-promise-reject-errors": "off",
"quotes": "off", "quotes": "off",
// We disable this while we're transitioning
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
}, },
}], }],
}; };

View file

@ -46,7 +46,7 @@ ipcMain.on('loudNotification', function(): void {
} }
}); });
let powerSaveBlockerId: number = null; let powerSaveBlockerId: number | null = null;
ipcMain.on('app_onAction', function(_ev: IpcMainEvent, payload) { ipcMain.on('app_onAction', function(_ev: IpcMainEvent, payload) {
switch (payload.action) { switch (payload.action) {
case 'call_state': { case 'call_state': {
@ -147,11 +147,11 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
case 'getPickleKey': case 'getPickleKey':
try { try {
ret = await keytar.getPassword("element.io", `${args[0]}|${args[1]}`); ret = await keytar?.getPassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be // migrate from riot.im (remove once we think there will no longer be
// logins from the time of riot.im) // logins from the time of riot.im)
if (ret === null) { if (ret === null) {
ret = await keytar.getPassword("riot.im", `${args[0]}|${args[1]}`); ret = await keytar?.getPassword("riot.im", `${args[0]}|${args[1]}`);
} }
} catch (e) { } catch (e) {
// if an error is thrown (e.g. keytar can't connect to the keychain), // if an error is thrown (e.g. keytar can't connect to the keychain),
@ -163,7 +163,7 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
case 'createPickleKey': case 'createPickleKey':
try { try {
const pickleKey = await randomArray(32); const pickleKey = await randomArray(32);
await keytar.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey); await keytar?.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey);
ret = pickleKey; ret = pickleKey;
} catch (e) { } catch (e) {
ret = null; ret = null;
@ -172,10 +172,10 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
case 'destroyPickleKey': case 'destroyPickleKey':
try { try {
await keytar.deletePassword("element.io", `${args[0]}|${args[1]}`); await keytar?.deletePassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be // migrate from riot.im (remove once we think there will no longer be
// logins from the time of riot.im) // logins from the time of riot.im)
await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`); await keytar?.deletePassword("riot.im", `${args[0]}|${args[1]}`);
} catch (e) {} } catch (e) {}
break; break;
case 'getDesktopCapturerSources': case 'getDesktopCapturerSources':

View file

@ -21,7 +21,7 @@ try {
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
keytar = require('keytar'); keytar = require('keytar');
} catch (e) { } catch (e) {
if (e.code === "MODULE_NOT_FOUND") { if ((<NodeJS.ErrnoException>e).code === "MODULE_NOT_FOUND") {
console.log("Keytar isn't installed; secure key storage is disabled."); console.log("Keytar isn't installed; secure key storage is disabled.");
} else { } else {
console.warn("Keytar unexpected error:", e); console.warn("Keytar unexpected error:", e);

View file

@ -27,7 +27,7 @@ export function _td(text: string): string {
type SubstitutionValue = number | string; type SubstitutionValue = number | string;
interface IVariables { interface IVariables {
[key: string]: SubstitutionValue; [key: string]: SubstitutionValue | undefined;
count?: number; count?: number;
} }
@ -66,13 +66,13 @@ export function _t(text: string, variables: IVariables = {}): string {
type Component = () => void; type Component = () => void;
type TypedStore = Store<{ locale?: string | string[] }>; type TypedStore = Store<{ locale?: string[] }>;
export class AppLocalization { export class AppLocalization {
private static readonly STORE_KEY = "locale"; private static readonly STORE_KEY = "locale";
private readonly store: TypedStore; private readonly store: TypedStore;
private readonly localizedComponents: Set<Component>; private readonly localizedComponents?: Set<Component>;
constructor({ store, components = [] }: { store: TypedStore, components: Component[] }) { constructor({ store, components = [] }: { store: TypedStore, components: Component[] }) {
counterpart.registerTranslations("en", this.fetchTranslationJson("en_EN")); counterpart.registerTranslations("en", this.fetchTranslationJson("en_EN"));
@ -86,7 +86,8 @@ export class AppLocalization {
this.store = store; this.store = store;
if (this.store.has(AppLocalization.STORE_KEY)) { if (this.store.has(AppLocalization.STORE_KEY)) {
const locales = this.store.get(AppLocalization.STORE_KEY); const locales = this.store.get(AppLocalization.STORE_KEY);
this.setAppLocale(locales); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.setAppLocale(locales!);
} }
this.resetLocalizedUI(); this.resetLocalizedUI();
@ -110,7 +111,7 @@ export class AppLocalization {
return require(`./i18n/strings/${this.denormalize(locale)}.json`); return require(`./i18n/strings/${this.denormalize(locale)}.json`);
} catch (e) { } catch (e) {
console.log(`Could not fetch translation json for locale: '${locale}'`, e); console.log(`Could not fetch translation json for locale: '${locale}'`, e);
return null; return {};
} }
} }
@ -138,7 +139,7 @@ export class AppLocalization {
public resetLocalizedUI(): void { public resetLocalizedUI(): void {
console.log("Resetting the UI components after locale change"); console.log("Resetting the UI components after locale change");
this.localizedComponents.forEach(componentSetup => { this.localizedComponents?.forEach(componentSetup => {
if (typeof componentSetup === "function") { if (typeof componentSetup === "function") {
componentSetup(); componentSetup();
} }

View file

@ -86,7 +86,7 @@ export function getProfileFromDeeplink(args: string[]): string | undefined {
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) { if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) {
const parsedUrl = new URL(deeplinkUrl); const parsedUrl = new URL(deeplinkUrl);
if (parsedUrl.protocol === PROTOCOL) { if (parsedUrl.protocol === PROTOCOL) {
const ssoID = parsedUrl.searchParams.get(SEARCH_PARAM); const ssoID = parsedUrl.searchParams.get(SEARCH_PARAM)!;
const store = readStore(); const store = readStore();
console.log("Forwarding to profile: ", store[ssoID]); console.log("Forwarding to profile: ", store[ssoID]);
return store[ssoID]; return store[ssoID];

View file

@ -40,7 +40,7 @@ try {
ReindexError = seshatModule.ReindexError; ReindexError = seshatModule.ReindexError;
seshatSupported = true; seshatSupported = true;
} catch (e) { } catch (e) {
if (e.code === "MODULE_NOT_FOUND") { if ((<NodeJS.ErrnoException>e).code === "MODULE_NOT_FOUND") {
console.log("Seshat isn't installed, event indexing is disabled."); console.log("Seshat isn't installed, event indexing is disabled.");
} else { } else {
console.warn("Seshat unexpected error:", e); console.warn("Seshat unexpected error:", e);
@ -49,7 +49,7 @@ try {
const eventStorePath = path.join(app.getPath('userData'), 'EventStore'); const eventStorePath = path.join(app.getPath('userData'), 'EventStore');
let eventIndex: SeshatType = null; let eventIndex: SeshatType | null = null;
const seshatDefaultPassphrase = "DEFAULT_PASSPHRASE"; const seshatDefaultPassphrase = "DEFAULT_PASSPHRASE";
async function getOrCreatePassphrase(key: string): Promise<string> { async function getOrCreatePassphrase(key: string): Promise<string> {
@ -66,9 +66,8 @@ async function getOrCreatePassphrase(key: string): Promise<string> {
} catch (e) { } catch (e) {
console.log("Error getting the event index passphrase out of the secret store", e); console.log("Error getting the event index passphrase out of the secret store", e);
} }
} else {
return seshatDefaultPassphrase;
} }
return seshatDefaultPassphrase;
} }
const deleteContents = async (p: string): Promise<void> => { const deleteContents = async (p: string): Promise<void> => {
@ -180,7 +179,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
case 'addEventToIndex': case 'addEventToIndex':
try { try {
eventIndex.addEvent(args[0], args[1]); eventIndex?.addEvent(args[0], args[1]);
} catch (e) { } catch (e) {
sendError(payload.id, e); sendError(payload.id, e);
return; return;
@ -189,7 +188,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
case 'deleteEvent': case 'deleteEvent':
try { try {
ret = await eventIndex.deleteEvent(args[0]); ret = await eventIndex?.deleteEvent(args[0]);
} catch (e) { } catch (e) {
sendError(payload.id, e); sendError(payload.id, e);
return; return;
@ -198,7 +197,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
case 'commitLiveEvents': case 'commitLiveEvents':
try { try {
ret = await eventIndex.commit(); ret = await eventIndex?.commit();
} catch (e) { } catch (e) {
sendError(payload.id, e); sendError(payload.id, e);
return; return;
@ -207,7 +206,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
case 'searchEventIndex': case 'searchEventIndex':
try { try {
ret = await eventIndex.search(args[0]); ret = await eventIndex?.search(args[0]);
} catch (e) { } catch (e) {
sendError(payload.id, e); sendError(payload.id, e);
return; return;

View file

@ -22,7 +22,7 @@ import fs from "fs";
import { _t } from "./language-helper"; import { _t } from "./language-helper";
let trayIcon: Tray = null; let trayIcon: Tray | null = null;
export function hasTray(): boolean { export function hasTray(): boolean {
return (trayIcon !== null); return (trayIcon !== null);
@ -65,7 +65,7 @@ export function create(config: IConfig): void {
if (!favicons || favicons.length <= 0 || !favicons[0].startsWith('data:')) { if (!favicons || favicons.length <= 0 || !favicons[0].startsWith('data:')) {
if (lastFavicon !== null) { if (lastFavicon !== null) {
global.mainWindow.setIcon(defaultIcon); global.mainWindow.setIcon(defaultIcon);
trayIcon.setImage(defaultIcon); trayIcon?.setImage(defaultIcon);
lastFavicon = null; lastFavicon = null;
} }
return; return;
@ -88,12 +88,12 @@ export function create(config: IConfig): void {
} }
} }
trayIcon.setImage(newFavicon); trayIcon?.setImage(newFavicon);
global.mainWindow.setIcon(newFavicon); global.mainWindow.setIcon(newFavicon);
}); });
global.mainWindow.webContents.on('page-title-updated', function(ev, title) { global.mainWindow.webContents.on('page-title-updated', function(ev, title) {
trayIcon.setToolTip(title); trayIcon?.setToolTip(title);
}); });
} }

View file

@ -70,6 +70,7 @@ export function start(updateBaseUrl: string): void {
// I'm not even going to try to guess which feed style they'd use if they // I'm not even going to try to guess which feed style they'd use if they
// implemented it on Linux, or if it would be different again. // implemented it on Linux, or if it would be different again.
console.log('Auto update not supported on this platform'); console.log('Auto update not supported on this platform');
return;
} }
if (url) { if (url) {

View file

@ -50,7 +50,7 @@ function safeOpenURL(target: string): void {
// (for instance, open /bin/sh does indeed open a terminal // (for instance, open /bin/sh does indeed open a terminal
// with a shell, albeit with no arguments) // with a shell, albeit with no arguments)
const parsedUrl = url.parse(target); const parsedUrl = url.parse(target);
if (PERMITTED_URL_SCHEMES.indexOf(parsedUrl.protocol) > -1) { if (PERMITTED_URL_SCHEMES.includes(parsedUrl.protocol!)) {
// explicitly use the URL re-assembled by the url library, // explicitly use the URL re-assembled by the url library,
// so we know the url parser has understood all the parts // so we know the url parser has understood all the parts
// of the input string // of the input string
@ -69,7 +69,7 @@ function onWindowOrNavigate(ev: Event, target: string): void {
} }
function writeNativeImage(filePath: string, img: NativeImage): Promise<void> { function writeNativeImage(filePath: string, img: NativeImage): Promise<void> {
switch (filePath.split('.').pop().toLowerCase()) { switch (filePath.split('.').pop()?.toLowerCase()) {
case "jpg": case "jpg":
case "jpeg": case "jpeg":
return fs.promises.writeFile(filePath, img.toJPEG(100)); return fs.promises.writeFile(filePath, img.toJPEG(100));
@ -181,7 +181,7 @@ function cutCopyPasteSelectContextMenus(params: ContextMenuParams): MenuItemCons
options.push({ options.push({
label: word, label: word,
click: (menuItem, browserWindow) => { click: (menuItem, browserWindow) => {
browserWindow.webContents.replaceMisspelling(word); browserWindow?.webContents.replaceMisspelling(word);
}, },
}); });
}); });
@ -190,7 +190,7 @@ function cutCopyPasteSelectContextMenus(params: ContextMenuParams): MenuItemCons
}, { }, {
label: _t('Add to dictionary'), label: _t('Add to dictionary'),
click: (menuItem, browserWindow) => { click: (menuItem, browserWindow) => {
browserWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord); browserWindow?.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord);
}, },
}, { }, {
type: 'separator', type: 'separator',
@ -251,8 +251,9 @@ function onEditableContextMenu(ev: Event, params: ContextMenuParams) {
let userDownloadIndex = 0; let userDownloadIndex = 0;
const userDownloadMap = new Map<number, string>(); // Map from id to path const userDownloadMap = new Map<number, string>(); // Map from id to path
ipcMain.on('userDownloadAction', function(ev: IpcMainEvent, { id, open = false }) { ipcMain.on('userDownloadAction', function(ev: IpcMainEvent, { id, open = false }) {
if (open) { const path = userDownloadMap.get(id);
shell.openPath(userDownloadMap.get(id)); if (open && path) {
shell.openPath(path);
} }
userDownloadMap.delete(id); userDownloadMap.delete(id);
}); });

View file

@ -16,6 +16,7 @@
"dom" "dom"
], ],
"types": ["jest", "node"], "types": ["jest", "node"],
"strict": true
}, },
"include": [ "include": [
"./src/**/*.ts", "./src/**/*.ts",