]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor: eliminate remaining non-null assertions in ChargingStation and OCPP16Servic...
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 24 Mar 2026 16:26:31 +0000 (17:26 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 24 Mar 2026 16:26:31 +0000 (17:26 +0100)
- ChargingStation: replace 8 non-null assertions with optional chaining,
  nullish coalescing defaults, and null guards
- OCPP16ServiceUtils: add type narrowing guards for composite charging
  schedules, extract connector status variables with null checks,
  replace all 14 non-null assertions with safe access patterns

Zero non-null assertions remain across the entire src/ directory.

src/charging-station/ChargingStation.ts
src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts

index 0ad4fcf3476c27794cbca9fea1bbb4d8f5bb235b..ef405ca98a4fb9121fa2168ffd076ceae691d2a6 100644 (file)
@@ -454,8 +454,10 @@ export class ChargingStation extends EventEmitter {
   public getConnectorMaximumAvailablePower (connectorId: number): number {
     let connectorAmperageLimitationLimit: number | undefined
     const amperageLimitation = this.getAmperageLimitation()
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    if (amperageLimitation != null && amperageLimitation < this.stationInfo!.maximumAmperage!) {
+    if (
+      amperageLimitation != null &&
+      amperageLimitation < (this.stationInfo?.maximumAmperage ?? Infinity)
+    ) {
       const voltageOut = this.getVoltageOut()
       connectorAmperageLimitationLimit =
         (this.stationInfo?.currentOutType === CurrentType.AC
@@ -465,11 +467,9 @@ export class ChargingStation extends EventEmitter {
             amperageLimitation *
                 (this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors())
           )
-          : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-          DCElectricUtils.power(voltageOut, amperageLimitation)) / this.powerDivider!
+          : DCElectricUtils.power(voltageOut, amperageLimitation)) / (this.powerDivider ?? 1)
     }
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    const connectorMaximumPower = this.stationInfo!.maximumPower! / this.powerDivider!
+    const connectorMaximumPower = (this.stationInfo?.maximumPower ?? 0) / (this.powerDivider ?? 1)
     const chargingStationChargingProfilesLimit =
       // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
       getChargingStationChargingProfilesLimit(this)! / this.powerDivider!
@@ -873,8 +873,7 @@ export class ChargingStation extends EventEmitter {
       logger.error(`${this.logPrefix()} Error during reset stop phase:`, error)
       return
     }
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    await sleep(this.stationInfo!.resetTime!)
+    await sleep(this.stationInfo?.resetTime ?? 0)
     OCPPAuthServiceFactory.clearInstance(this)
     this.initialize()
     this.start()
@@ -906,9 +905,8 @@ export class ChargingStation extends EventEmitter {
       isNotEmptyString(this.stationInfo.supervisionUrlOcppKey)
     ) {
       setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey, url)
-    } else {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      this.stationInfo!.supervisionUrls = url
+    } else if (this.stationInfo != null) {
+      this.stationInfo.supervisionUrls = url
       this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl()
       this.saveStationInfo()
     }
@@ -1568,8 +1566,7 @@ export class ChargingStation extends EventEmitter {
         const patchLevelIndex = match.length - 1
         match[patchLevelIndex] = (
           convertToInt(match[patchLevelIndex]) +
-          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-          this.stationInfo.firmwareUpgrade!.versionUpgrade!.step!
+          (this.stationInfo.firmwareUpgrade?.versionUpgrade?.step ?? 1)
         ).toString()
         this.stationInfo.firmwareVersion = match.join('.')
       }
@@ -2115,10 +2112,10 @@ export class ChargingStation extends EventEmitter {
           >(this, RequestCommand.BOOT_NOTIFICATION, this.bootNotificationRequest, {
             skipBufferingOnError: true,
           })
-          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-          this.bootNotificationResponse!.currentTime = convertToDate(
-            this.bootNotificationResponse?.currentTime
-          )!
+          if (this.bootNotificationResponse != null) {
+            this.bootNotificationResponse.currentTime =
+              convertToDate(this.bootNotificationResponse.currentTime) ?? new Date()
+          }
           if (!this.inAcceptedState()) {
             ++registrationRetryCount
             await sleep(
@@ -2133,8 +2130,7 @@ export class ChargingStation extends EventEmitter {
         } while (
           !this.inAcceptedState() &&
           (this.stationInfo?.registrationMaxRetries === -1 ||
-            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-            registrationRetryCount <= this.stationInfo!.registrationMaxRetries!)
+            registrationRetryCount <= (this.stationInfo?.registrationMaxRetries ?? 0))
         )
       }
       if (!this.inAcceptedState()) {
@@ -2164,8 +2160,7 @@ export class ChargingStation extends EventEmitter {
   private async reconnect (): Promise<void> {
     if (
       this.stationInfo?.autoReconnectMaxRetries === -1 ||
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      this.wsConnectionRetryCount < this.stationInfo!.autoReconnectMaxRetries!
+      this.wsConnectionRetryCount < (this.stationInfo?.autoReconnectMaxRetries ?? 0)
     ) {
       ++this.wsConnectionRetryCount
       const reconnectDelay =
index 0604a4babd122595850b85772bc587b4d766a8d0..0edd3aa216721becc9f1807dce4ea9b59f0c668b 100644 (file)
@@ -235,31 +235,33 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     if (chargingScheduleHigher == null && chargingScheduleLower != null) {
       return OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleLower, compositeInterval)
     }
-    const compositeChargingScheduleHigher: OCPP16ChargingSchedule | undefined =
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleHigher!, compositeInterval)
-    const compositeChargingScheduleLower: OCPP16ChargingSchedule | undefined =
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleLower!, compositeInterval)
+    if (chargingScheduleHigher == null || chargingScheduleLower == null) {
+      return undefined
+    }
+    const compositeChargingScheduleHigher = OCPP16ServiceUtils.composeChargingSchedule(
+      chargingScheduleHigher,
+      compositeInterval
+    )
+    const compositeChargingScheduleLower = OCPP16ServiceUtils.composeChargingSchedule(
+      chargingScheduleLower,
+      compositeInterval
+    )
+    if (compositeChargingScheduleHigher == null || compositeChargingScheduleLower == null) {
+      return compositeChargingScheduleHigher ?? compositeChargingScheduleLower
+    }
     const compositeChargingScheduleHigherInterval: Interval = {
       end: addSeconds(
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        compositeChargingScheduleHigher!.startSchedule!,
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        compositeChargingScheduleHigher!.duration!
+        compositeChargingScheduleHigher.startSchedule ?? new Date(),
+        compositeChargingScheduleHigher.duration ?? 0
       ),
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      start: compositeChargingScheduleHigher!.startSchedule!,
+      start: compositeChargingScheduleHigher.startSchedule ?? new Date(),
     }
     const compositeChargingScheduleLowerInterval: Interval = {
       end: addSeconds(
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        compositeChargingScheduleLower!.startSchedule!,
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        compositeChargingScheduleLower!.duration!
+        compositeChargingScheduleLower.startSchedule ?? new Date(),
+        compositeChargingScheduleLower.duration ?? 0
       ),
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      start: compositeChargingScheduleLower!.startSchedule!,
+      start: compositeChargingScheduleLower.startSchedule ?? new Date(),
     }
     const higherFirst = isBefore(
       compositeChargingScheduleHigherInterval.start,
@@ -273,11 +275,9 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     ) {
       return {
         ...compositeChargingScheduleLower,
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        ...compositeChargingScheduleHigher!,
+        ...compositeChargingScheduleHigher,
         chargingSchedulePeriod: [
-          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-          ...compositeChargingScheduleHigher!.chargingSchedulePeriod.map(schedulePeriod => {
+          ...compositeChargingScheduleHigher.chargingSchedulePeriod.map(schedulePeriod => {
             return {
               ...schedulePeriod,
               startPeriod: higherFirst
@@ -289,8 +289,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
                   ),
             }
           }),
-          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-          ...compositeChargingScheduleLower!.chargingSchedulePeriod.map(schedulePeriod => {
+          ...compositeChargingScheduleLower.chargingSchedulePeriod.map(schedulePeriod => {
             return {
               ...schedulePeriod,
               startPeriod: higherFirst
@@ -319,11 +318,9 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     }
     return {
       ...compositeChargingScheduleLower,
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      ...compositeChargingScheduleHigher!,
+      ...compositeChargingScheduleHigher,
       chargingSchedulePeriod: [
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        ...compositeChargingScheduleHigher!.chargingSchedulePeriod.map(schedulePeriod => {
+        ...compositeChargingScheduleHigher.chargingSchedulePeriod.map(schedulePeriod => {
           return {
             ...schedulePeriod,
             startPeriod: higherFirst
@@ -335,8 +332,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
                 ),
           }
         }),
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        ...compositeChargingScheduleLower!.chargingSchedulePeriod
+        ...compositeChargingScheduleLower.chargingSchedulePeriod
           .filter((schedulePeriod, index) => {
             if (
               higherFirst &&
@@ -355,8 +351,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             }
             if (
               higherFirst &&
-              // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-              index < compositeChargingScheduleLower!.chargingSchedulePeriod.length - 1 &&
+              index < compositeChargingScheduleLower.chargingSchedulePeriod.length - 1 &&
               !isWithinInterval(
                 addSeconds(
                   compositeChargingScheduleLowerInterval.start,
@@ -370,8 +365,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               isWithinInterval(
                 addSeconds(
                   compositeChargingScheduleLowerInterval.start,
-                  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-                  compositeChargingScheduleLower!.chargingSchedulePeriod[index + 1].startPeriod
+                  compositeChargingScheduleLower.chargingSchedulePeriod[index + 1].startPeriod
                 ),
                 {
                   end: compositeChargingScheduleHigherInterval.end,
@@ -564,25 +558,26 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       logger.warn(
         `${chargingStation.logPrefix()} ${moduleName}.setChargingProfile: Trying to set a charging profile on connector id ${connectorId.toString()} with an improper attribute type for the charging profiles array, applying proper type deferred initialization`
       )
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      chargingStation.getConnectorStatus(connectorId)!.chargingProfiles = []
+      const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+      if (connectorStatus != null) {
+        connectorStatus.chargingProfiles = []
+      }
     }
     cp.chargingSchedule.startSchedule = convertToDate(cp.chargingSchedule.startSchedule)
     cp.validFrom = convertToDate(cp.validFrom)
     cp.validTo = convertToDate(cp.validTo)
     let cpReplaced = false
     if (isNotEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      for (const [index, chargingProfile] of chargingStation
-        .getConnectorStatus(connectorId)!
-        .chargingProfiles!.entries()) {
+      const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+      for (const [index, chargingProfile] of (connectorStatus?.chargingProfiles ?? []).entries()) {
         if (
           chargingProfile.chargingProfileId === cp.chargingProfileId ||
           (chargingProfile.stackLevel === cp.stackLevel &&
             chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)
         ) {
-          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-          chargingStation.getConnectorStatus(connectorId)!.chargingProfiles![index] = cp
+          if (connectorStatus?.chargingProfiles != null) {
+            connectorStatus.chargingProfiles[index] = cp
+          }
           cpReplaced = true
         }
       }