From: Jérôme Benoit Date: Tue, 24 Mar 2026 16:26:31 +0000 (+0100) Subject: refactor: eliminate remaining non-null assertions in ChargingStation and OCPP16Servic... X-Git-Tag: ocpp-server@v3.4.0~23 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=47456f32c8f71a083928a6645fe0bb8b560712bc;p=e-mobility-charging-stations-simulator.git refactor: eliminate remaining non-null assertions in ChargingStation and OCPP16ServiceUtils - 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. --- diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 0ad4fcf3..ef405ca9 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -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 { 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 = diff --git a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts index 0604a4ba..0edd3aa2 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts @@ -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 } }