Address null-safety identified by TSC compiler v6

There are no actual functional changes. This just adds many additional
annotations and function which ensure type safety and null safety.
This commit is contained in:
Max Berger
2026-03-25 21:32:32 +01:00
parent fd067a6a59
commit 951cfde278
19 changed files with 461 additions and 350 deletions

View File

@@ -49,7 +49,7 @@ class CollectionsCache {
/**
* @param {string} user
* @param {string} password
* @param {?string} password
* @param {import("../models/collection.js").Collection} principal_collection
* @param {function(string):void} onerror
* @param {function(Array<import("../models/collection.js").Collection>, Array<import("../api/sharing.js").Share>, boolean):void} displayData
@@ -63,9 +63,9 @@ class CollectionsCache {
let loading_scene = new LoadingScene();
push_scene(loading_scene);
let collections = null;
let shares = null;
let error = null;
/** @type {?Array<import("../models/collection.js").Collection>} */ let collections = null;
/** @type {?Array<import("../api/sharing.js").Share>} */ let shares = null;
/** @type {?string} */ let error = null;
let check_if_completed = () => {
if (!is_current_scene(loading_scene)) {
@@ -101,7 +101,7 @@ class CollectionsCache {
/**
* @param {string} user
* @param {string} password
* @param {?string} password
* @param {function(string):void} onerror
* @param {function(Array<import("../api/sharing.js").Share>):void} displayData
*/
@@ -132,7 +132,7 @@ class CollectionsCache {
/**
* @param {string} user
* @param {string} password
* @param {?string} password
* @param {function(string):void} onerror
* @param {function(import("../api/sharing.js").ServerFeatures):void} displayData
*/

View File

@@ -31,10 +31,14 @@ export class ErrorHandler {
/**
* Sets an error message for a given key.
* @param {string} errorMessage
* @param {?string} errorMessage
*/
setError(errorMessage) {
this._update([errorMessage]);
if (errorMessage) {
this._update([errorMessage]);
} else {
this.clearError();
}
}
/**

View File

@@ -30,6 +30,7 @@ export class FormValidator {
*/
constructor(error_handler) {
this.error_handler = error_handler;
/** @type {Array<{field: HTMLInputElement, validation_method: function(): ?string}>} */
this.validation_methods = [];
}
@@ -51,8 +52,8 @@ export class FormValidator {
*/
validate() {
let errorMessages = [];
for (let { field, validation_method } of this.validation_methods) {
let errorMessage = validation_method(field);
for (let { validation_method } of this.validation_methods) {
let errorMessage = validation_method();
if (errorMessage) {
errorMessages.push(errorMessage);
}
@@ -136,7 +137,9 @@ export function validate_color(input, field_name) {
}
return null;
};
}/**
}
/**
* Validates that the input matches a specific string.
* @param {HTMLInputElement} input
* @param {string} target

View File

@@ -48,11 +48,7 @@ export function random_uuid() {
export function random_hex(length) {
let bytes = new Uint8Array(Math.ceil(length / 2));
window.crypto.getRandomValues(bytes);
// Fallback for compatibility with older browsers which may not have padStart
return bytes.reduce((s, b) => {
let hex = b.toString(16);
return s + (String.prototype["padStart"] ? hex["padStart"](2, "0") : ("0" + hex).slice(-2));
}, "").substring(0, length);
return bytes.reduce((s, b) => s + b.toString(16).padStart(2, "0"), "").substring(0, length);
}
/**
@@ -119,3 +115,30 @@ export function setupSelectAll() {
}
});
}
/**
* Get an element by its ID and throw an error if it's not found.
* @param {string} id The ID of the element to find.
* @return {HTMLElement} The found element.
*/
export function get_element_by_id(id) {
const element = document.getElementById(id);
if (!element) {
throw new Error("Element with ID '" + id + "' not found");
}
return element;
}
/**
* Get an element by a selector and throw an error if it's not found.
* @param {ParentNode} node The parent node to search within.
* @param {string} selector The CSS selector to use.
* @return {HTMLElement} The found element.
*/
export function get_element(node, selector) {
const element = node.querySelector(selector);
if (!element) {
throw new Error("Element with selector '" + selector + "' not found");
}
return /** @type {HTMLElement} */ (element);
}

View File

@@ -24,12 +24,12 @@ export function displayPermissions(permissions, node) {
permissions = (permissions || "").toLowerCase();
if (permissions === "rw") {
const roElement = node.querySelector("[data-name=ro]");
if (roElement) {
if (roElement && roElement.parentNode) {
roElement.parentNode.removeChild(roElement);
}
} else if (permissions === "r") {
const rwElement = node.querySelector("[data-name=rw]");
if (rwElement) {
if (rwElement && rwElement.parentNode) {
rwElement.parentNode.removeChild(rwElement);
}
} else {