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",
"quotes": "off",
// We disable this while we're transitioning
"@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) {
switch (payload.action) {
case 'call_state': {
@ -147,11 +147,11 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
case 'getPickleKey':
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
// logins from the time of riot.im)
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) {
// 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':
try {
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;
} catch (e) {
ret = null;
@ -172,10 +172,10 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
case 'destroyPickleKey':
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
// 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) {}
break;
case 'getDesktopCapturerSources':

View file

@ -21,7 +21,7 @@ try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
keytar = require('keytar');
} 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.");
} else {
console.warn("Keytar unexpected error:", e);

View file

@ -27,7 +27,7 @@ export function _td(text: string): string {
type SubstitutionValue = number | string;
interface IVariables {
[key: string]: SubstitutionValue;
[key: string]: SubstitutionValue | undefined;
count?: number;
}
@ -66,13 +66,13 @@ export function _t(text: string, variables: IVariables = {}): string {
type Component = () => void;
type TypedStore = Store<{ locale?: string | string[] }>;
type TypedStore = Store<{ locale?: string[] }>;
export class AppLocalization {
private static readonly STORE_KEY = "locale";
private readonly store: TypedStore;
private readonly localizedComponents: Set<Component>;
private readonly localizedComponents?: Set<Component>;
constructor({ store, components = [] }: { store: TypedStore, components: Component[] }) {
counterpart.registerTranslations("en", this.fetchTranslationJson("en_EN"));
@ -86,7 +86,8 @@ export class AppLocalization {
this.store = store;
if (this.store.has(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();
@ -110,7 +111,7 @@ export class AppLocalization {
return require(`./i18n/strings/${this.denormalize(locale)}.json`);
} catch (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 {
console.log("Resetting the UI components after locale change");
this.localizedComponents.forEach(componentSetup => {
this.localizedComponents?.forEach(componentSetup => {
if (typeof componentSetup === "function") {
componentSetup();
}

View file

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

View file

@ -40,7 +40,7 @@ try {
ReindexError = seshatModule.ReindexError;
seshatSupported = true;
} 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.");
} else {
console.warn("Seshat unexpected error:", e);
@ -49,7 +49,7 @@ try {
const eventStorePath = path.join(app.getPath('userData'), 'EventStore');
let eventIndex: SeshatType = null;
let eventIndex: SeshatType | null = null;
const seshatDefaultPassphrase = "DEFAULT_PASSPHRASE";
async function getOrCreatePassphrase(key: string): Promise<string> {
@ -66,9 +66,8 @@ async function getOrCreatePassphrase(key: string): Promise<string> {
} catch (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> => {
@ -180,7 +179,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
case 'addEventToIndex':
try {
eventIndex.addEvent(args[0], args[1]);
eventIndex?.addEvent(args[0], args[1]);
} catch (e) {
sendError(payload.id, e);
return;
@ -189,7 +188,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
case 'deleteEvent':
try {
ret = await eventIndex.deleteEvent(args[0]);
ret = await eventIndex?.deleteEvent(args[0]);
} catch (e) {
sendError(payload.id, e);
return;
@ -198,7 +197,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
case 'commitLiveEvents':
try {
ret = await eventIndex.commit();
ret = await eventIndex?.commit();
} catch (e) {
sendError(payload.id, e);
return;
@ -207,7 +206,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
case 'searchEventIndex':
try {
ret = await eventIndex.search(args[0]);
ret = await eventIndex?.search(args[0]);
} catch (e) {
sendError(payload.id, e);
return;

View file

@ -22,7 +22,7 @@ import fs from "fs";
import { _t } from "./language-helper";
let trayIcon: Tray = null;
let trayIcon: Tray | null = null;
export function hasTray(): boolean {
return (trayIcon !== null);
@ -65,7 +65,7 @@ export function create(config: IConfig): void {
if (!favicons || favicons.length <= 0 || !favicons[0].startsWith('data:')) {
if (lastFavicon !== null) {
global.mainWindow.setIcon(defaultIcon);
trayIcon.setImage(defaultIcon);
trayIcon?.setImage(defaultIcon);
lastFavicon = null;
}
return;
@ -88,12 +88,12 @@ export function create(config: IConfig): void {
}
}
trayIcon.setImage(newFavicon);
trayIcon?.setImage(newFavicon);
global.mainWindow.setIcon(newFavicon);
});
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
// implemented it on Linux, or if it would be different again.
console.log('Auto update not supported on this platform');
return;
}
if (url) {

View file

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

View file

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