Fix new JS verification errors and force specific TSC version

The new TSC compiler does stricter checking on the JS documentation
strings. All documentation strings have been updated to pass with
the current version (7.0.2)

In addition, the version of the TSC compiler used during the github
action will be fixed to 7.0.2, so that we don't get these type of
sudden errors again in the future. Unfortunately this means we need
to periodically update this manually.
This commit is contained in:
Max Berger
2026-07-12 09:31:54 +02:00
parent 1e31d757cb
commit 1f1e94340d
8 changed files with 45 additions and 45 deletions

View File

@@ -293,7 +293,7 @@ jobs:
node-version: 24
- name: JS Type Check
run: |
npx -p typescript tsc -p radicale/web/jsconfig.json
npx -y -p typescript@7.0.2 tsc -p radicale/web/jsconfig.json
lint:
name: Lint

View File

@@ -28,7 +28,7 @@ import { create_request, to_error_message } from "./common.js";
* Find the principal collection.
* @param {?string} user
* @param {?string} password
* @param {function(?Collection, ?string):void} callback Returns result or error
* @param {(collection: Collection | null, error: string | null) => void} callback Returns result or error
* @return {XMLHttpRequest}
*/
export function get_principal(user, password, callback) {
@@ -81,7 +81,7 @@ export function get_principal(user, password, callback) {
* @param {string} user
* @param {?string} password
* @param {Collection} collection
* @param {function(?Array<Collection>, ?string):void} callback Returns result or error
* @param {(collections: Array<Collection> | null, error: string | null) => void} callback Returns result or error
* @return {XMLHttpRequest}
*/
export function get_collections(user, password, collection, callback) {
@@ -267,7 +267,7 @@ function _parse_collection(response, collection_href) {
* @param {?string} password
* @param {string} collection_href Must always start and end with /.
* @param {File} file
* @param {function(?string):void} callback Returns error or null
* @param {(error: string | null) => void} callback Returns error or null
* @return {XMLHttpRequest}
*/
export function upload_collection(user, password, collection_href, file, callback) {
@@ -291,7 +291,7 @@ export function upload_collection(user, password, collection_href, file, callbac
* @param {string} user
* @param {?string} password
* @param {Collection} collection
* @param {function(?string):void} callback Returns error or null
* @param {(error: string | null) => void} callback Returns error or null
* @return {XMLHttpRequest}
*/
export function delete_collection(user, password, collection, callback) {
@@ -315,7 +315,7 @@ export function delete_collection(user, password, collection, callback) {
* @param {?string} password
* @param {Collection} collection
* @param {boolean} create
* @param {function(?string):void} callback Returns error or null
* @param {(error: string | null) => void} callback Returns error or null
* @return {XMLHttpRequest}
*/
function create_edit_collection(user, password, collection, create, callback) {
@@ -394,7 +394,7 @@ function create_edit_collection(user, password, collection, create, callback) {
* @param {string} user
* @param {?string} password
* @param {Collection} collection
* @param {function(?string):void} callback Returns error or null
* @param {(error: string | null) => void} callback Returns error or null
* @return {XMLHttpRequest}
*/
export function create_collection(user, password, collection, callback) {
@@ -405,7 +405,7 @@ export function create_collection(user, password, collection, callback) {
* @param {string} user
* @param {?string} password
* @param {Collection} collection
* @param {function(?string):void} callback Returns error or null
* @param {(error: string | null) => void} callback Returns error or null
* @return {XMLHttpRequest}
*/
export function edit_collection(user, password, collection, callback) {

View File

@@ -41,9 +41,9 @@ import { create_request, to_error_message } from "./common.js";
* @param {?string} password
* @param {string} path
* @param {object} body
* @param {function(string):void} on_success
* @param {?function():void} on_not_found
* @param {?function(string):void} on_error
* @param {(response: string) => void} on_success
* @param {(() => void) | null} on_not_found
* @param {((error: string) => void) | null} on_error
* @returns {XMLHttpRequest}
*/
function call_sharing_api(
@@ -92,7 +92,7 @@ function call_sharing_api(
/**
* @param {string} user
* @param {?string} password
* @param {function(import("../api/sharing.js").ServerFeatures, ?string):void} callback
* @param {(features: import("../api/sharing.js").ServerFeatures, error: string | null) => void} callback
*/
export function discover_server_features(user, password, callback) {
call_sharing_api(
@@ -163,12 +163,12 @@ export const BDAY_CONFIG = Object.freeze([
]);
export class ShareConfig {
/** @type {Record<string, any>} */
_values = {};
/**
* @param {ShareConfig|Record<string, any>} [data]
*/
constructor(data = {}) {
/** @type {Record<string, any>} */
this._values = {};
let rawData = data;
if (data instanceof ShareConfig) {
rawData = data._values;
@@ -310,8 +310,8 @@ export class Share {
/** @type {number} */ this.TimestampUpdated = data.TimestampUpdated || 0;
/** @type {Object<String, String>} */ this.Properties = data.Properties || {};
/** @type {string} */ this.Conversion = data.Conversion || "";
/** @type {ShareActions} */ this._Actions = new ShareActions();
this.Actions = data.Actions || {};
/** @type {ShareActions} */
this._Actions = data.Actions instanceof ShareActions ? data.Actions : new ShareActions(data.Actions || {});
}
/**
@@ -351,7 +351,7 @@ export class Share {
* @param {string} user
* @param {?string} password
* @param {?import("../models/collection.js").Collection} collection
* @param {function(Array<Share>, ?string):void} callback
* @param {(shares: Array<Share>, error: string | null) => void} callback
*/
export function reload_sharing_list(user, password, collection, callback) {
let body = collection ? { PathMapped: decodeURIComponent(collection.href) } : {};
@@ -412,7 +412,7 @@ export function get_property_key(type, property) {
* @param {string} user
* @param {?string} password
* @param {Share} share
* @param {function(?string):void} callback
* @param {(error: string | null) => void} callback
*/
export function add_share_by_token(
user,
@@ -452,7 +452,7 @@ export function add_share_by_token(
* @param {string} user
* @param {?string} password
* @param {Share} share
* @param {function(?string):void} callback
* @param {(error: string | null) => void} callback
*/
export function add_share_by_map(
user,
@@ -494,7 +494,7 @@ export function add_share_by_map(
* @param {string} user
* @param {?string} password
* @param {Share} share
* @param {function(?string):void} callback
* @param {(error: string | null) => void} callback
*/
export function delete_share_by_token(
user,
@@ -526,7 +526,7 @@ export function delete_share_by_token(
* @param {string} user
* @param {?string} password
* @param {Share} share
* @param {function(?string):void} callback
* @param {(error: string | null) => void} callback
*/
export function delete_share_by_map(
user,
@@ -557,7 +557,7 @@ export function delete_share_by_map(
* @param {string} user
* @param {?string} password
* @param {Share} share
* @param {function(?string):void} callback
* @param {(error: string | null) => void} callback
*/
export function update_share_by_token(
user,
@@ -597,7 +597,7 @@ export function update_share_by_token(
* @param {string} user
* @param {?string} password
* @param {Share} share
* @param {function(?string):void} callback
* @param {(error: string | null) => void} callback
*/
export function update_share_by_map(
user,
@@ -641,7 +641,7 @@ export function update_share_by_map(
* @param {string} user
* @param {?string} password
* @param {Share} share
* @param {function(?string):void} callback
* @param {(error: string | null) => void} callback
*/
export function update_incoming_share(
user,

View File

@@ -42,7 +42,7 @@ export class CollectionsScene {
* @param {string} user
* @param {?string} password
* @param {Collection} principal_collection The princial collection
* @param {function(?string):void} onerror Called when an error occurs, before the
* @param {(error: string | null) => void} onerror Called when an error occurs, before the
* scene is popped.
*/
constructor(user, password, principal_collection, onerror) {

View File

@@ -169,10 +169,10 @@ function update_share_list(user, password, collection, errorHandler) {
* @param {import('../api/sharing.js').Share} share
* @param {HTMLElement} template
* @param {string} delete_label
* @param {function(string, string, import('../api/sharing.js').Share, function(?string):void):void} delete_action
* @param {function():void} [onDeleteSuccess] Optional extra callback after a successful delete.
* @param {(user: string, password: string | null, share: import('../api/sharing.js').Share, callback: (error: string | null) => void) => void} delete_action
* @param {(() => void) | null} [onDeleteSuccess] Optional extra callback after a successful delete.
*/
function add_share_row_node(user, password, collection, share, template, delete_label, delete_action, onDeleteSuccess) {
function add_share_row_node(user, password, collection, share, template, delete_label, delete_action, onDeleteSuccess = null) {
let pathortoken = share["PathOrToken"] || "";
let node = /** @type {HTMLElement} */ (template.cloneNode(true));
node.classList.remove("hidden");

View File

@@ -31,7 +31,7 @@ class CollectionsCache {
this.server_features = null;
/** @type {?XMLHttpRequest} */ this.collections_req = null;
/** @type {?XMLHttpRequest} */ this.shares_req = null;
/** @type {?Array<{ onerror: function(string):void, displayData: function(Array<import("../api/sharing.js").Share>):void }>} */
/** @type {Array<{ onerror: (error: string) => void, displayData: (shares: Array<import("../api/sharing.js").Share>) => void }> | null} */
this._sharing_callbacks = null;
}
@@ -54,8 +54,8 @@ class CollectionsCache {
* @param {string} user
* @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
* @param {(error: string) => void} onerror
* @param {(collections: Array<import("../models/collection.js").Collection>, shares: Array<import("../api/sharing.js").Share>, loaded: boolean) => void} displayData
*/
getChildCollections(user, password, principal_collection, onerror, displayData) {
if (this.child_collections !== null && this.incoming_shares !== null) {
@@ -105,8 +105,8 @@ class CollectionsCache {
/**
* @param {string} user
* @param {?string} password
* @param {function(string):void} onerror
* @param {function(Array<import("../api/sharing.js").Share>):void} displayData
* @param {(error: string) => void} onerror
* @param {(shares: Array<import("../api/sharing.js").Share>) => void} displayData
*/
getSharingList(user, password, onerror, displayData) {
if (this.incoming_shares !== null) {
@@ -140,8 +140,8 @@ class CollectionsCache {
/**
* @param {string} user
* @param {?string} password
* @param {function(string):void} onerror
* @param {function(import("../api/sharing.js").ServerFeatures):void} displayData
* @param {(error: string) => void} onerror
* @param {(features: import("../api/sharing.js").ServerFeatures) => void} displayData
*/
getServerFeatures(user, password, onerror, displayData) {
if (this.server_features !== null) {

View File

@@ -30,13 +30,13 @@ export class FormValidator {
*/
constructor(error_handler) {
this.error_handler = error_handler;
/** @type {Array<{field: HTMLInputElement, validation_method: function(): ?string}>} */
/** @type {Array<{field: HTMLInputElement, validation_method: () => string | null}>} */
this.validation_methods = [];
}
/**
* @param {HTMLInputElement} field
* @param {function(): ?string} validation_method
* @param {() => string | null} validation_method
*/
addValidator(field, validation_method) {
this.validation_methods.push({ field, validation_method });
@@ -67,7 +67,7 @@ export class FormValidator {
* Validates that the input is not empty.
* @param {HTMLInputElement} input
* @param {string} field_name
* @returns{function(): ?string}
* @returns {() => string | null}
*/
export function validate_non_empty(input, field_name) {
return () => {
@@ -83,7 +83,7 @@ export function validate_non_empty(input, field_name) {
* @param {HTMLInputElement} input
* @param {string} target
* @param {string} field_name
* @returns {function(): ?string}
* @returns {() => string | null}
*/
export function validate_not_empty_or_equals(input, target, field_name) {
return () => {
@@ -102,7 +102,7 @@ export function validate_not_empty_or_equals(input, target, field_name) {
* Validates that the input is a valid HREF.
* @param {HTMLInputElement} input
* @param {string} field_name
* @returns {function(): ?string}
* @returns {() => string | null}
*/
export function validate_href(input, field_name) {
return () => {
@@ -124,7 +124,7 @@ export function validate_href(input, field_name) {
* Validates that the input is a valid color.
* @param {HTMLInputElement} input
* @param {string} field_name
* @returns {function(): ?string}
* @returns {() => string | null}
*/
export function validate_color(input, field_name) {
return () => {
@@ -144,7 +144,7 @@ export function validate_color(input, field_name) {
* @param {HTMLInputElement} input
* @param {string} target
* @param {string} field_name
* @returns {function(): ?string}
* @returns {() => string | null}
*/
export function validate_equals(input, target, field_name) {
return () => {
@@ -160,7 +160,7 @@ export function validate_equals(input, target, field_name) {
* Validates that at least one file is selected in a file input.
* @param {HTMLInputElement} input
* @param {string} field_name
* @returns {function(): ?string}
* @returns {() => string | null}
*/
export function validate_files(input, field_name) {
return () => {
@@ -175,7 +175,7 @@ export function validate_files(input, field_name) {
* Validates that the input is a valid integer (if not empty).
* @param {HTMLInputElement} input
* @param {string} field_name
* @returns {function(): ?string}
* @returns {() => string | null}
*/
export function validate_integer(input, field_name) {
return () => {

View File

@@ -156,7 +156,7 @@ export function get_element(node, selector) {
*
* @param {string} str
* @param {number} max
* @returns {str}
* @returns {string}
*/
export function trim_to_max(str, max) {
if (str.length > max - 2) {