convertToDate,
formatDurationMilliSeconds,
getRandomInteger,
- isValidTime,
+ isValidDate,
logPrefix,
logger,
secureRandom,
this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.stopAbsoluteDuration ===
false ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- !isValidTime(this.connectorsStatus.get(connectorId)!.stopDate)
+ !isValidDate(this.connectorsStatus.get(connectorId)!.stopDate)
) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.connectorsStatus.get(connectorId)!.stopDate = new Date(
`${
this.stationInfo?.supervisionUrlOcppConfiguration === true &&
isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- isNotEmptyString(getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!)?.value)
- ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!)!.value
+ isNotEmptyString(getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey)?.value)
+ ? getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey)?.value
: this.configuredSupervisionUrl.href
}/${this.stationInfo?.chargingStationId}`
)
this.stationInfo?.supervisionUrlOcppConfiguration === true &&
isNotEmptyString(this.stationInfo.supervisionUrlOcppKey)
) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey!, url)
+ setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey, url)
} else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.stationInfo!.supervisionUrls = url
public startAutomaticTransactionGenerator (connectorIds?: number[]): void {
this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(this)
if (isNotEmptyArray(connectorIds)) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- for (const connectorId of connectorIds!) {
+ for (const connectorId of connectorIds) {
this.automaticTransactionGenerator?.startConnector(connectorId)
}
} else {
public stopAutomaticTransactionGenerator (connectorIds?: number[]): void {
if (isNotEmptyArray(connectorIds)) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- for (const connectorId of connectorIds!) {
+ for (const connectorId of connectorIds) {
this.automaticTransactionGenerator?.stopConnector(connectorId)
}
} else {
createSerialNumber(stationTemplate, stationInfo)
stationInfo.voltageOut = this.getVoltageOut(stationInfo)
if (isNotEmptyArray(stationTemplate.power)) {
- stationTemplate.power = stationTemplate.power as number[]
const powerArrayRandomIndex = Math.floor(secureRandom() * stationTemplate.power.length)
stationInfo.maximumPower =
stationTemplate.powerUnit === PowerUnits.KILO_WATT
? stationTemplate.power[powerArrayRandomIndex] * 1000
: stationTemplate.power[powerArrayRandomIndex]
} else {
- stationTemplate.power = stationTemplate.power as number
stationInfo.maximumPower =
stationTemplate.powerUnit === PowerUnits.KILO_WATT
- ? stationTemplate.power * 1000
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ stationTemplate.power! * 1000
: stationTemplate.power
}
stationInfo.maximumAmperage = this.getMaximumAmperage(stationInfo)
stationTemplate.firmwareVersionPattern ?? Constants.SEMVER_PATTERN
if (
isNotEmptyString(stationInfo.firmwareVersion) &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- !new RegExp(stationInfo.firmwareVersionPattern).test(stationInfo.firmwareVersion!)
+ !new RegExp(stationInfo.firmwareVersionPattern).test(stationInfo.firmwareVersion)
) {
logger.warn(
`${this.logPrefix()} Firmware version '${stationInfo.firmwareVersion}' in template file ${
) {
const patternGroup =
this.stationInfo.firmwareUpgrade?.versionUpgrade?.patternGroup ??
- this.stationInfo.firmwareVersion?.split('.').length
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const match = new RegExp(this.stationInfo.firmwareVersionPattern!)
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- .exec(this.stationInfo.firmwareVersion!)
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ?.slice(1, patternGroup! + 1)
+ this.stationInfo.firmwareVersion.split('.').length
+ const match = new RegExp(this.stationInfo.firmwareVersionPattern)
+ .exec(this.stationInfo.firmwareVersion)
+ ?.slice(1, patternGroup + 1)
if (match != null) {
const patchLevelIndex = match.length - 1
match[patchLevelIndex] = (
if (
this.stationInfo?.supervisionUrlOcppConfiguration === true &&
isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!) == null
+ getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey) == null
) {
addConfigurationKey(
this,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.stationInfo.supervisionUrlOcppKey!,
+ this.stationInfo.supervisionUrlOcppKey,
this.configuredSupervisionUrl.href,
{ reboot: true }
)
} else if (
this.stationInfo?.supervisionUrlOcppConfiguration === false &&
isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!) != null
+ getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey) != null
) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- deleteConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!, { save: false })
+ deleteConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey, { save: false })
}
if (
isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey!) == null
+ getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey) == null
) {
addConfigurationKey(
this,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.stationInfo!.amperageLimitationOcppKey!,
+ this.stationInfo.amperageLimitationOcppKey,
// prettier-ignore
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- (this.stationInfo!.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo)).toString()
+ (this.stationInfo.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo)).toString()
)
}
if (getConfigurationKey(this, StandardParametersKey.SupportedFeatureProfiles) == null) {
private getAmperageLimitation (): number | undefined {
if (
isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- getConfigurationKey(this, this.stationInfo!.amperageLimitationOcppKey!) != null
+ getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey) != null
) {
return (
- convertToInt(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- getConfigurationKey(this, this.stationInfo!.amperageLimitationOcppKey!)!.value
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ) / getAmperageLimitationUnitDivider(this.stationInfo!)
+ convertToInt(getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey)?.value) /
+ getAmperageLimitationUnitDivider(this.stationInfo)
)
}
}
let configuredSupervisionUrlIndex: number
switch (Configuration.getSupervisionUrlDistribution()) {
case SupervisionUrlDistribution.RANDOM:
- configuredSupervisionUrlIndex = Math.floor(
- secureRandom() * (supervisionUrls as string[]).length
- )
+ configuredSupervisionUrlIndex = Math.floor(secureRandom() * supervisionUrls.length)
break
case SupervisionUrlDistribution.ROUND_ROBIN:
case SupervisionUrlDistribution.CHARGING_STATION_AFFINITY:
SupervisionUrlDistribution.CHARGING_STATION_AFFINITY
}`
)
- configuredSupervisionUrlIndex = (this.index - 1) % (supervisionUrls as string[]).length
+ configuredSupervisionUrlIndex = (this.index - 1) % supervisionUrls.length
break
}
- configuredSupervisionUrl = (supervisionUrls as string[])[configuredSupervisionUrlIndex]
+ configuredSupervisionUrl = supervisionUrls[configuredSupervisionUrlIndex]
} else {
- configuredSupervisionUrl = supervisionUrls as string
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ configuredSupervisionUrl = supervisionUrls!
}
if (isNotEmptyString(configuredSupervisionUrl)) {
return new URL(configuredSupervisionUrl)
isEmptyString,
isNotEmptyArray,
isNotEmptyString,
- isValidTime,
+ isValidDate,
logger,
secureRandom
} from '../utils/index.js'
}
connectorStatus.chargingProfiles =
connectorStatus.transactionId != null && isNotEmptyArray(connectorStatus.chargingProfiles)
- ? connectorStatus.chargingProfiles?.filter(
+ ? connectorStatus.chargingProfiles.filter(
chargingProfile => chargingProfile.transactionId !== connectorStatus.transactionId
)
: []
const getConfiguredMaxNumberOfConnectors = (stationTemplate: ChargingStationTemplate): number => {
let configuredMaxNumberOfConnectors = 0
if (isNotEmptyArray(stationTemplate.numberOfConnectors)) {
- const numberOfConnectors = stationTemplate.numberOfConnectors as number[]
+ const numberOfConnectors = stationTemplate.numberOfConnectors
configuredMaxNumberOfConnectors =
numberOfConnectors[Math.floor(secureRandom() * numberOfConnectors.length)]
} else if (stationTemplate.numberOfConnectors != null) {
- configuredMaxNumberOfConnectors = stationTemplate.numberOfConnectors as number
+ configuredMaxNumberOfConnectors = stationTemplate.numberOfConnectors
} else if (stationTemplate.Connectors != null && stationTemplate.Evses == null) {
configuredMaxNumberOfConnectors =
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
logPrefix: string
): boolean => {
if (
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- (isValidTime(chargingProfile.validFrom) && isBefore(currentDate, chargingProfile.validFrom!)) ||
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- (isValidTime(chargingProfile.validTo) && isAfter(currentDate, chargingProfile.validTo!))
+ (isValidDate(chargingProfile.validFrom) && isBefore(currentDate, chargingProfile.validFrom)) ||
+ (isValidDate(chargingProfile.validTo) && isAfter(currentDate, chargingProfile.validTo))
) {
logger.debug(
`${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${
chargingProfile.chargingProfileId
} is not valid for the current date ${
- currentDate instanceof Date ? currentDate.toISOString() : currentDate
+ isDate(currentDate) ? currentDate.toISOString() : currentDate
}`
)
return false
)
return false
}
- if (!isValidTime(chargingProfile.chargingSchedule.startSchedule)) {
+ if (!isValidDate(chargingProfile.chargingSchedule.startSchedule)) {
logger.error(
`${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has an invalid startSchedule date defined`
)
): boolean => {
const chargingSchedule = chargingProfile.chargingSchedule
let recurringIntervalTranslated = false
- let recurringInterval: Interval
+ let recurringInterval: Interval | undefined
switch (chargingProfile.recurrencyKind) {
case RecurrencyKindType.DAILY:
recurringInterval = {
`${logPrefix} ${moduleName}.prepareRecurringChargingProfile: Recurring ${
chargingProfile.recurrencyKind
} charging profile id ${chargingProfile.chargingProfileId} recurrency time interval [${toDate(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- recurringInterval!.start
+ recurringInterval?.start as Date
).toISOString()}, ${toDate(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- recurringInterval!.end
+ recurringInterval?.end as Date
).toISOString()}] has not been properly translated to current date ${
- currentDate instanceof Date ? currentDate.toISOString() : currentDate
+ isDate(currentDate) ? currentDate.toISOString() : currentDate
} `
)
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const connectorStatus = chargingStation.getConnectorStatus(connectorId!)
if (connectorId != null && isNotEmptyArray(connectorStatus?.chargingProfiles)) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- connectorStatus!.chargingProfiles = []
+ connectorStatus.chargingProfiles = []
logger.debug(
`${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${connectorId}`
)
const { id, chargingProfilePurpose, stackLevel } = commandPayload
let clearedCP = false
if (isNotEmptyArray(chargingProfiles)) {
- chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
+ chargingProfiles.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
let clearCurrentCP = false
if (chargingProfile.chargingProfileId === id) {
clearCurrentCP = true
)
? getRandomFloatFluctuatedRounded(
getLimitFromSampledValueTemplateCustomValue(
- powerPerPhaseSampledValueTemplates.L1?.value,
+ powerPerPhaseSampledValueTemplates.L1.value,
connectorMaximumPowerPerPhase / unitDivider,
connectorMinimumPowerPerPhase / unitDivider,
{
fallbackValue: connectorMinimumPowerPerPhase / unitDivider
}
),
- powerPerPhaseSampledValueTemplates.L1?.fluctuationPercent ??
+ powerPerPhaseSampledValueTemplates.L1.fluctuationPercent ??
Constants.DEFAULT_FLUCTUATION_PERCENT
)
: undefined
)
? getRandomFloatFluctuatedRounded(
getLimitFromSampledValueTemplateCustomValue(
- powerPerPhaseSampledValueTemplates.L2?.value,
+ powerPerPhaseSampledValueTemplates.L2.value,
connectorMaximumPowerPerPhase / unitDivider,
connectorMinimumPowerPerPhase / unitDivider,
{
fallbackValue: connectorMinimumPowerPerPhase / unitDivider
}
),
- powerPerPhaseSampledValueTemplates.L2?.fluctuationPercent ??
+ powerPerPhaseSampledValueTemplates.L2.fluctuationPercent ??
Constants.DEFAULT_FLUCTUATION_PERCENT
)
: undefined
)
? getRandomFloatFluctuatedRounded(
getLimitFromSampledValueTemplateCustomValue(
- powerPerPhaseSampledValueTemplates.L3?.value,
+ powerPerPhaseSampledValueTemplates.L3.value,
connectorMaximumPowerPerPhase / unitDivider,
connectorMinimumPowerPerPhase / unitDivider,
{
fallbackValue: connectorMinimumPowerPerPhase / unitDivider
}
),
- powerPerPhaseSampledValueTemplates.L3?.fluctuationPercent ??
+ powerPerPhaseSampledValueTemplates.L3.fluctuationPercent ??
Constants.DEFAULT_FLUCTUATION_PERCENT
)
: undefined
)
? getRandomFloatFluctuatedRounded(
getLimitFromSampledValueTemplateCustomValue(
- currentPerPhaseSampledValueTemplates.L1?.value,
+ currentPerPhaseSampledValueTemplates.L1.value,
connectorMaximumAmperage,
connectorMinimumAmperage,
{
fallbackValue: connectorMinimumAmperage
}
),
- currentPerPhaseSampledValueTemplates.L1?.fluctuationPercent ??
+ currentPerPhaseSampledValueTemplates.L1.fluctuationPercent ??
Constants.DEFAULT_FLUCTUATION_PERCENT
)
: undefined
)
? getRandomFloatFluctuatedRounded(
getLimitFromSampledValueTemplateCustomValue(
- currentPerPhaseSampledValueTemplates.L2?.value,
+ currentPerPhaseSampledValueTemplates.L2.value,
connectorMaximumAmperage,
connectorMinimumAmperage,
{
fallbackValue: connectorMinimumAmperage
}
),
- currentPerPhaseSampledValueTemplates.L2?.fluctuationPercent ??
+ currentPerPhaseSampledValueTemplates.L2.fluctuationPercent ??
Constants.DEFAULT_FLUCTUATION_PERCENT
)
: undefined
)
? getRandomFloatFluctuatedRounded(
getLimitFromSampledValueTemplateCustomValue(
- currentPerPhaseSampledValueTemplates.L3?.value,
+ currentPerPhaseSampledValueTemplates.L3.value,
connectorMaximumAmperage,
connectorMinimumAmperage,
{
fallbackValue: connectorMinimumAmperage
}
),
- currentPerPhaseSampledValueTemplates.L3?.fluctuationPercent ??
+ currentPerPhaseSampledValueTemplates.L3.fluctuationPercent ??
Constants.DEFAULT_FLUCTUATION_PERCENT
)
: undefined
// This is intentional
}
- public static ajvErrorsToErrorType (errors: ErrorObject[] | null | undefined): ErrorType {
+ public static ajvErrorsToErrorType (errors: ErrorObject[] | undefined | null): ErrorType {
if (isNotEmptyArray(errors)) {
for (const error of errors as DefinedError[]) {
switch (error.keyword) {
): void {
if (isNotEmptyArray(payload.hashIds)) {
payload.hashIds = payload.hashIds
- ?.map(hashId => {
+ .map(hashId => {
if (this.uiServer.chargingStations.has(hashId)) {
return hashId
}
}
// More efficient time validation function than the one provided by date-fns
-export const isValidTime = (date: Date | number | undefined): boolean => {
+export const isValidDate = (date: Date | number | undefined): date is Date | number => {
if (typeof date === 'number') {
return !isNaN(date)
} else if (isDate(date)) {
}
export const convertToDate = (
- value: Date | string | number | null | undefined
-): Date | null | undefined => {
+ value: Date | string | number | undefined | null
+): Date | undefined | null => {
if (value == null) {
return value
}
return Math.trunc(value)
}
if (isString(value)) {
- changedValue = parseInt(value as string)
+ changedValue = parseInt(value)
}
if (isNaN(changedValue)) {
throw new Error(`Cannot convert to integer: '${String(value)}'`)
}
let changedValue: number = value as number
if (isString(value)) {
- changedValue = parseFloat(value as string)
+ changedValue = parseFloat(value)
}
if (isNaN(changedValue)) {
throw new Error(`Cannot convert to float: '${String(value)}'`)
// Check the type
if (typeof value === 'boolean') {
return value
- } else if (isString(value) && ((value as string).toLowerCase() === 'true' || value === '1')) {
+ } else if (isString(value) && (value.toLowerCase() === 'true' || value === '1')) {
result = true
} else if (typeof value === 'number' && value === 1) {
result = true
return timeSeries.map(timeSeriesItem => timeSeriesItem.value)
}
-export const isObject = (item: unknown): boolean => {
+export const isObject = (item: unknown): item is object => {
return item != null && typeof item === 'object' && !Array.isArray(item)
}
}
export const hasOwnProp = (object: unknown, property: PropertyKey): boolean => {
- return isObject(object) && Object.hasOwn(object as object, property)
+ return isObject(object) && Object.hasOwn(object, property)
}
export const isCFEnvironment = (): boolean => {
return env.VCAP_APPLICATION != null
}
-export const isIterable = <T>(obj: T): boolean => {
- return obj != null ? typeof obj[Symbol.iterator as keyof T] === 'function' : false
-}
-
-const isString = (value: unknown): boolean => {
+const isString = (value: unknown): value is string => {
return typeof value === 'string'
}
-export const isEmptyString = (value: unknown): boolean => {
- return value == null || (isString(value) && (value as string).trim().length === 0)
+export const isEmptyString = (value: unknown): value is string | undefined | null => {
+ return value == null || (isString(value) && value.trim().length === 0)
}
-export const isNotEmptyString = (value: unknown): boolean => {
- return isString(value) && (value as string).trim().length > 0
+export const isNotEmptyString = (value: unknown): value is string => {
+ return isString(value) && value.trim().length > 0
}
-export const isEmptyArray = (object: unknown): boolean => {
+export const isEmptyArray = (object: unknown): object is unknown[] => {
return Array.isArray(object) && object.length === 0
}
-export const isNotEmptyArray = (object: unknown): boolean => {
+export const isNotEmptyArray = (object: unknown): object is unknown[] => {
return Array.isArray(object) && object.length > 0
}
isEmptyString,
isNotEmptyArray,
isNotEmptyString,
- isValidTime,
+ isValidDate,
logPrefix,
max,
min,
isEmptyArray,
isEmptyObject,
isEmptyString,
- isIterable,
isNotEmptyArray,
isNotEmptyString,
isObject,
- isValidTime,
+ isValidDate,
max,
min,
once,
})
await it('Verify isValidTime()', () => {
- expect(isValidTime(undefined)).toBe(false)
- expect(isValidTime(null)).toBe(false)
- expect(isValidTime('')).toBe(false)
- expect(isValidTime({})).toBe(false)
- expect(isValidTime([])).toBe(false)
- expect(isValidTime(new Map())).toBe(false)
- expect(isValidTime(new Set())).toBe(false)
- expect(isValidTime(new WeakMap())).toBe(false)
- expect(isValidTime(new WeakSet())).toBe(false)
- expect(isValidTime(-1)).toBe(true)
- expect(isValidTime(0)).toBe(true)
- expect(isValidTime(1)).toBe(true)
- expect(isValidTime(-0.5)).toBe(true)
- expect(isValidTime(0.5)).toBe(true)
- expect(isValidTime(new Date())).toBe(true)
+ expect(isValidDate(undefined)).toBe(false)
+ expect(isValidDate(-1)).toBe(true)
+ expect(isValidDate(0)).toBe(true)
+ expect(isValidDate(1)).toBe(true)
+ expect(isValidDate(-0.5)).toBe(true)
+ expect(isValidDate(0.5)).toBe(true)
+ expect(isValidDate(new Date())).toBe(true)
})
await it('Verify convertToDate()', () => {
expect(hasOwnProp({ 1: '1' }, 2)).toBe(false)
})
- await it('Verify isIterable()', () => {
- expect(isIterable('')).toBe(true)
- expect(isIterable(' ')).toBe(true)
- expect(isIterable('test')).toBe(true)
- expect(isIterable(undefined)).toBe(false)
- expect(isIterable(null)).toBe(false)
- expect(isIterable(0)).toBe(false)
- expect(isIterable([0, 1])).toBe(true)
- expect(isIterable({ 1: 1 })).toBe(false)
- expect(isIterable(new Map())).toBe(true)
- expect(isIterable(new Set())).toBe(true)
- expect(isIterable(new WeakMap())).toBe(false)
- expect(isIterable(new WeakSet())).toBe(false)
- })
-
await it('Verify isEmptyString()', () => {
expect(isEmptyString('')).toBe(true)
expect(isEmptyString(' ')).toBe(true)
return value as T
}
-// const isIterable = <T>(obj: T): boolean => {
-// if (obj == null) {
-// return false
-// }
-// return typeof (obj as unknown as Iterable<T>)[Symbol.iterator] === 'function'
-// }
-
-// const ifNotIterableDo = <T>(obj: T, cb: () => void): void => {
-// if (isIterable(obj) === false) cb()
-// }
-
// export const compose = <T>(...fns: ((arg: T) => T)[]): ((x: T) => T) => {
// return (x: T) => fns.reduceRight((y, fn) => fn(y), x)
// }