Skip to main content

Bibliotheken und eigene .d.ts-Dateien

Die otris-Bibliotheken otrUpgrade, otrAssert und util.otrLogger bringen eigene Typings mit, größtenteils mit deutscher Doku. Anders als portalScripting.d.ts sind sie als Module geschrieben (export declare ...). Man holt sich ihre Typen deshalb gezielt per import().

Voraussetzung: Modulnamen auflösen

VS Code muss Modulnamen wie "otrUpgrade" oder "DexRecordLib" einer Datei zuordnen. In unserer jsconfig.json erledigen das zwei Einstellungen: typeRoots findet alle Typings in typings/, deren Dateiname dem Modulnamen entspricht. paths deckt den Rest ab, also abweichende Dateinamen und unsere Bibliotheken in src/. Fehlt ein Name, wird der Import zu any und prüft nichts. Heute fehlen zwei Bibliotheken, die per Name geladen werden:

"paths": {
  "DexNotification_API": ["./src/DexUtility.cat/DexNotification_API.mjs"],
  "DexDossierLib": ["./src/DexDossier.cat/DexDossierLib.js"]
}

Getestet mit TypeScript 6.0.3: otrAssert, util.otrLogger, otrUpgrade_TypeDef und DexRecordReference werden voll geprüft. DexNotification_API (in DexRecord_ACT_Create.mjs, DexRecordCategory_ACT_DropAction.mjs) und DexDossierLib (in ADMIN_Folder_ScriptList_DexCustomFields.js, Gadget_DEXPRO_EditCustomFields.js) melden "Cannot find module".

Konfigurationsobjekte gegen otrUpgrade-Specs prüfen

Bei otrUpgrade lohnt sich das besonders: Ordner, Felder und Register werden als große Objekte beschrieben, und ein Tippfehler in einem Schlüssel fällt sonst erst auf dem Server auf. Aus DexDossier_InitFolder.js:

/** @type {import("otrUpgrade_TypeDef").NewPublicFolderActionSpec} */
const allFiles_actions = {
    "AllowArchive": false,
    "AllowCopyTo": false,
    "AllowMoveTo": false,
    "AllowForward": false,
}

/** @type {import("otrUpgrade_TypeDef").NewPublicFolderSpec} */
const allFilesFolder = {
    "Label": "DexDossier_AllDossierFiles",
    "MultiLangLabel": "de:Alle Akten;en:All files",
    "Type": "dynamicpublic",
    "Released": true,
    "FilterFileType": dexDossierTypesArr,
    "Action": allFiles_actions,
}

Fehlt einer Spec ein Feld, das wir brauchen, wird sie mit & erweitert statt auf any auszuweichen (DexDossierLib.js):

/**
 * @type {Array<import("otrUpgrade_TypeDef").FileTypeFieldSpec & {FileType?: string}>}
 */
const fields = [
    { Name: "HR_COMMENT", Type: FDT.F_RULER, Label: "de:Kommentar;en:Comment" },
    { Name: "Comment", Type: FDT.F_HISTORY, Label: "de:Kommentar;en:Comment" },

Typisiertes require

Wenn der Laufzeitname eines Moduls nicht zum Typing-Namen passt, verbindet ein @typedef mit Cast beides. Aus Gadget_DexRecordCategory_FiletypeFilter.js:

/**
 * @typedef {import("gadgetAPI")} gadgetAPI
 * @typedef {import("otrUpgrade")} otrUpgrade
 */

const gadgetAPI = /** @type {gadgetAPI} */ (require("gadgetAPI.module.gadgetAPI"));
const otrUpgrade = /** @type {otrUpgrade} */ (require("otrUpgrade"));

Einzelne Typen lassen sich genauso holen, z.B. die Log-Level des Loggers: /** @type {import("util.otrLogger").LogLevels} */. Ein Wert wie "VERBOSE" wird dann als Fehler markiert.

Eigene .d.ts-Datei

Für Dinge, die mehrere Skripte betreffen, pflegen wir eigene Deklarationsdateien in typings_dexpro/. Der Ordner steht bereits in include. Was dort heute liegt:

Datei

Inhalt

docfile_extensions.d.ts

Methoden, die wir zur Laufzeit an DocFile hängen, z.B. getParamObject, getParamValue

context_extension.d.ts

Undokumentierte context-Methoden wie createSystemUser

classes.d.ts

Eigene Klassen wie ReturnObject

otrisModules.d.ts

Macht require("otris.tree") und die anderen otris.*-Module typisiert

DexDossier.d.ts

Der Typ DexDossier mit den Feldern unserer Akten

DEXPRO__*.d.ts, DexRecordLib.d.ts, RIB_DossierLib.d.ts u.a.

Typen unserer Bibliotheken

Eine neue Datei folgt diesem Muster:

// typings_dexpro/beispiel.d.ts

// Eigene Methode, die zur Laufzeit an DocFile gehängt wird
interface DocFile {
    /** Speichert RIB-Daten in die Mappe */
    saveRIBDataToRecord(data: object): boolean;
}

// Skript-Parameter, die der Server als globale Variable bereitstellt
declare var ProjectID: string;

Die Datei darf kein import oder export auf oberster Ebene enthalten, sonst gelten die Deklarationen nicht mehr global. otrisModules.d.ts zeigt, wie es trotzdem geht: Dort steht export nur innerhalb von declare module "…" { }.