From bf0ab6797fba5403423eab996f1974cc785afc1e Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 16 Dec 2024 11:29:34 +0100 Subject: [PATCH] front: replace casts with assertions This is safer (we get a type error if a type is changed), and more readable. Enable @typescript-eslint/non-nullable-type-assertion-style to make sure we don't introduce more of these. Signed-off-by: Simon Ser --- front/.eslintrc | 1 + .../components/RangeEditionLeftPanel.tsx | 3 +- .../editor/tools/rangeEdition/utils.ts | 4 +-- .../editor/tools/routeEdition/utils.ts | 4 +-- .../components/SwitchEditionLayers.tsx | 6 +--- .../applications/operationalStudies/utils.ts | 31 +++++-------------- .../Map/WarpedMap/SimulationWarpedMap.tsx | 10 +++--- .../src/common/Map/WarpedMap/core/helpers.ts | 4 +-- .../src/common/Map/WarpedMap/core/quadtree.ts | 2 +- front/src/common/Selector/Selector.tsx | 6 ++-- front/src/index.tsx | 2 +- .../src/modules/rollingStock/helpers/utils.ts | 6 ++-- .../SimulationResultsExport.tsx | 2 +- .../components/ChartHelpers/ChartHelpers.ts | 1 + .../study/components/AddOrEditStudyModal.tsx | 2 +- front/src/test-data/geojson.ts | 2 +- front/src/utils/timeManipulation.ts | 2 +- 17 files changed, 33 insertions(+), 55 deletions(-) diff --git a/front/.eslintrc b/front/.eslintrc index d6dff6fbd4b..13df1c51db7 100644 --- a/front/.eslintrc +++ b/front/.eslintrc @@ -46,6 +46,7 @@ "@typescript-eslint/no-unnecessary-type-assertion": "error", "@typescript-eslint/no-unsafe-return": "error", "@typescript-eslint/no-unsafe-call": "error", + "@typescript-eslint/non-nullable-type-assertion-style": "error", "@typescript-eslint/ban-types": [ "error", diff --git a/front/src/applications/editor/tools/rangeEdition/components/RangeEditionLeftPanel.tsx b/front/src/applications/editor/tools/rangeEdition/components/RangeEditionLeftPanel.tsx index db72749fde8..e707a478e33 100644 --- a/front/src/applications/editor/tools/rangeEdition/components/RangeEditionLeftPanel.tsx +++ b/front/src/applications/editor/tools/rangeEdition/components/RangeEditionLeftPanel.tsx @@ -15,7 +15,6 @@ import type { SpeedSectionPslEntity, AvailableSwitchPositions, SwitchPosition, - ApplicableTrackRange, } from 'applications/editor/tools/rangeEdition/types'; import { makeSpeedRestrictionTrackRanges, @@ -158,7 +157,7 @@ const RangeEditionLeftPanel = () => { true ); if (returnedExtra) { - newRouteExtra[routeId] = last(trackRangesWithBothDirections) as ApplicableTrackRange; + newRouteExtra[routeId] = last(trackRangesWithBothDirections)!; } return trackRangesWithBothDirections; }); diff --git a/front/src/applications/editor/tools/rangeEdition/utils.ts b/front/src/applications/editor/tools/rangeEdition/utils.ts index f3e018aec7c..f219d187f37 100644 --- a/front/src/applications/editor/tools/rangeEdition/utils.ts +++ b/front/src/applications/editor/tools/rangeEdition/utils.ts @@ -188,7 +188,7 @@ export function getTrackRangeFeatures( itemType: 'TrackRangeExtremity', rangeIndex, }), - point(last(track.geometry.coordinates) as Position, { + point(last(track.geometry.coordinates)!, { ...properties, id: `speedSectionRangeExtremity::${rangeIndex}::${end}`, track: range.track, @@ -304,7 +304,7 @@ export function generatePslSignFeatures( export function getPointAt(track: TrackSectionEntity, at: number): Position { const dataLength = track.properties.length; if (at <= 0) return track.geometry.coordinates[0]; - if (at >= dataLength) return last(track.geometry.coordinates) as Position; + if (at >= dataLength) return last(track.geometry.coordinates)!; const computedLength = length(track); return along(track.geometry, (at * computedLength) / dataLength).geometry.coordinates; diff --git a/front/src/applications/editor/tools/routeEdition/utils.ts b/front/src/applications/editor/tools/routeEdition/utils.ts index 8847ce8a50e..2d51876dad2 100644 --- a/front/src/applications/editor/tools/routeEdition/utils.ts +++ b/front/src/applications/editor/tools/routeEdition/utils.ts @@ -97,8 +97,8 @@ export function computeRouteGeometry( const isFirst = !i; const isLast = i === trackRanges.length - 1; - const p1 = first(track.geometry.coordinates) as Position; - const p2 = last(track.geometry.coordinates) as Position; + const p1 = first(track.geometry.coordinates)!; + const p2 = last(track.geometry.coordinates)!; // Weird case of only range: if (isFirst && isLast) { diff --git a/front/src/applications/editor/tools/switchEdition/components/SwitchEditionLayers.tsx b/front/src/applications/editor/tools/switchEdition/components/SwitchEditionLayers.tsx index 520ec218fbf..ac0d4bb43cb 100644 --- a/front/src/applications/editor/tools/switchEdition/components/SwitchEditionLayers.tsx +++ b/front/src/applications/editor/tools/switchEdition/components/SwitchEditionLayers.tsx @@ -2,7 +2,6 @@ import { useContext, useEffect, useMemo, useState } from 'react'; import { featureCollection, point } from '@turf/helpers'; import nearestPoint from '@turf/nearest-point'; -import type { Position } from 'geojson'; import { first, last } from 'lodash'; import { useTranslation } from 'react-i18next'; import { Layer, Popup, Source } from 'react-map-gl/maplibre'; @@ -98,10 +97,7 @@ const SwitchEditionLayers = () => { const trackSectionPoints = hoveredTrack.geometry.coordinates; const closest = nearestPoint( mousePosition, - featureCollection([ - point(first(trackSectionPoints) as Position), - point(last(trackSectionPoints) as Position), - ]) + featureCollection([point(first(trackSectionPoints)!), point(last(trackSectionPoints)!)]) ); setState({ diff --git a/front/src/applications/operationalStudies/utils.ts b/front/src/applications/operationalStudies/utils.ts index 6bc87398f60..573c3ec8a10 100644 --- a/front/src/applications/operationalStudies/utils.ts +++ b/front/src/applications/operationalStudies/utils.ts @@ -129,7 +129,7 @@ export const formatElectrificationRanges = ( // We know we will find one because currentProfile is still defined const associatedProfile = electricalProfiles.find( (profile) => profile.stop >= currentElectrification.stop - ) as ElectricalRangesData; + )!; return { electrificationUsage: { @@ -146,7 +146,7 @@ export const formatElectrificationRanges = ( // We know we will find one because theirs last stops are the same const associatedProfile = electricalProfiles.find( (profile) => profile.stop >= currentElectrification.stop - ) as ElectricalRangesData; + )!; return { electrificationUsage: { @@ -168,23 +168,9 @@ export const preparePathPropertiesData = ( trainSchedulePath: TrainScheduleResult['path'], t: TFunction ): PathPropertiesFormatted => { - const formattedSlopes = transformBoundariesDataToPositionDataArray( - slopes as NonNullable, - length, - 'gradient' - ); - - const formattedCurves = transformBoundariesDataToPositionDataArray( - curves as NonNullable, - length, - 'radius' - ); - - const electrificationsRanges = transformBoundariesDataToRangesData( - electrifications as NonNullable, - length - ); - + const formattedSlopes = transformBoundariesDataToPositionDataArray(slopes!, length, 'gradient'); + const formattedCurves = transformBoundariesDataToPositionDataArray(curves!, length, 'radius'); + const electrificationsRanges = transformBoundariesDataToRangesData(electrifications!, length); const electricalProfilesRanges = transformBoundariesDataToRangesData(electricalProfiles, length); const electrificationRanges = formatElectrificationRanges( @@ -192,10 +178,7 @@ export const preparePathPropertiesData = ( electricalProfilesRanges ); - const voltageRanges = getPathVoltages( - electrifications as NonNullable, - length - ); + const voltageRanges = getPathVoltages(electrifications!, length); const operationalPointsWithAllWaypoints = upsertMapWaypointsInOperationalPoints( trainSchedulePath, @@ -209,7 +192,7 @@ export const preparePathPropertiesData = ( curves: formattedCurves, slopes: formattedSlopes, operationalPoints: operationalPointsWithAllWaypoints, - geometry: geometry as NonNullable, + geometry: geometry!, voltages: voltageRanges, }; }; diff --git a/front/src/common/Map/WarpedMap/SimulationWarpedMap.tsx b/front/src/common/Map/WarpedMap/SimulationWarpedMap.tsx index b70de78d4bc..50c60e27ce5 100644 --- a/front/src/common/Map/WarpedMap/SimulationWarpedMap.tsx +++ b/front/src/common/Map/WarpedMap/SimulationWarpedMap.tsx @@ -4,7 +4,7 @@ import bbox from '@turf/bbox'; import { lineString } from '@turf/helpers'; import type { BBox2d } from '@turf/helpers/dist/js/lib/geojson'; import length from '@turf/length'; -import type { Feature, FeatureCollection, LineString, Position } from 'geojson'; +import type { Feature, FeatureCollection, LineString } from 'geojson'; import { clamp, first, isEmpty, isNil, last, mapValues, omitBy } from 'lodash'; import type { LngLatBoundsLike } from 'maplibre-gl'; import { PiLinkBold, PiLinkBreakBold } from 'react-icons/pi'; @@ -103,9 +103,9 @@ const SimulationWarpedMap = ({ const size = !rotate ? height : width; // we don't clip the path - const transformedPath = transform(path, false) as typeof path; - const latStart = (first(transformedPath.geometry.coordinates) as Position)[1]; - const latEnd = (last(transformedPath.geometry.coordinates) as Position)[1]; + const transformedPath = transform(path, false)!; + const latStart = first(transformedPath.geometry.coordinates)![1]; + const latEnd = last(transformedPath.geometry.coordinates)![1]; /* * Here, `y` is the function provided by d3 to scale distance in meters from the beginning of the path to pixels @@ -140,7 +140,7 @@ const SimulationWarpedMap = ({ [warpedBBox[0], latTop], [warpedBBox[2], latBottom], ], - }) as typeof transformedPath; + })!; const clippedPathBBox = bbox(clippedPath) as BBox2d; const lngAverage = (clippedPathBBox[0] + clippedPathBBox[2]) / 2; diff --git a/front/src/common/Map/WarpedMap/core/helpers.ts b/front/src/common/Map/WarpedMap/core/helpers.ts index 516d8ac1b9e..6929bb0c98d 100644 --- a/front/src/common/Map/WarpedMap/core/helpers.ts +++ b/front/src/common/Map/WarpedMap/core/helpers.ts @@ -43,9 +43,9 @@ export function getSamples( const step = l / (samples - 1); for (let i = 0; i < samples; i++) { if (!i) { - points.push(point(first(line.geometry.coordinates) as Position)); + points.push(point(first(line.geometry.coordinates)!)); } else if (i === samples - 1) { - points.push(point(last(line.geometry.coordinates) as Position)); + points.push(point(last(line.geometry.coordinates)!)); } else { points.push(along(line, step * i, { units: 'meters' })); } diff --git a/front/src/common/Map/WarpedMap/core/quadtree.ts b/front/src/common/Map/WarpedMap/core/quadtree.ts index a6bf7486858..ffb924139c8 100644 --- a/front/src/common/Map/WarpedMap/core/quadtree.ts +++ b/front/src/common/Map/WarpedMap/core/quadtree.ts @@ -70,7 +70,7 @@ export function getQuadTree>); + newQuads.push(quad.children[k]!); } } } diff --git a/front/src/common/Selector/Selector.tsx b/front/src/common/Selector/Selector.tsx index 3f522ca268f..6d487b3acba 100644 --- a/front/src/common/Selector/Selector.tsx +++ b/front/src/common/Selector/Selector.tsx @@ -40,7 +40,7 @@ const SelectorItem = ({ updateData: (newData: { [key: string]: string }) => void; }; }) => { - const inputValue = extraColumn?.data[item.id as string] || ''; + const inputValue = extraColumn?.data[item.id!] || ''; const isDisabled = isDefaultItem || !extraColumn; const isWarning = inputValue === '' && !isDisabled; @@ -104,11 +104,11 @@ const SelectorItem = ({ sm noMargin disabled={isDefaultItem} - value={isDefaultItem ? extraColumn.defaultValue : extraColumn.data[item.id as string]} + value={isDefaultItem ? extraColumn.defaultValue : extraColumn.data[item.id!]} onChange={(e) => extraColumn.updateData({ ...extraColumn.data, - [item.id as string]: e.target.value, + [item.id!]: e.target.value, }) } /> diff --git a/front/src/index.tsx b/front/src/index.tsx index 76961943ba3..8e474ddadc5 100644 --- a/front/src/index.tsx +++ b/front/src/index.tsx @@ -25,5 +25,5 @@ export default function Container() { ); } -const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); +const root = ReactDOM.createRoot(document.getElementById('root')!); root.render(); diff --git a/front/src/modules/rollingStock/helpers/utils.ts b/front/src/modules/rollingStock/helpers/utils.ts index 92a37422d1f..c969ebc7236 100644 --- a/front/src/modules/rollingStock/helpers/utils.ts +++ b/front/src/modules/rollingStock/helpers/utils.ts @@ -53,9 +53,7 @@ export const getDefaultRollingStockMode = (selectedMode: string | null): EffortC : null; const getDefaultMultiUnitsParameter = (parameter: string): MultiUnitsParameter => { - const { min, max, units } = RS_SCHEMA_PROPERTIES.find( - (rsParam) => rsParam.title === parameter - ) as SchemaProperty; + const { min, max, units } = RS_SCHEMA_PROPERTIES.find((rsParam) => rsParam.title === parameter)!; return { min: min!, max: max!, @@ -157,7 +155,7 @@ export const rollingStockEditorQueryArg = ( comfort_acceleration: data.comfortAcceleration, const_gamma: data.constGamma, inertia_coefficient: data.inertiaCoefficient, - mass: handleUnitValue({ unit: 'kg', value: data.mass.value }, data.mass, data.mass) as number, // Back-end needs value in kg. + mass: handleUnitValue({ unit: 'kg', value: data.mass.value }, data.mass, data.mass)!, // Back-end needs value in kg. rolling_resistance: { A: handleUnitValue( { unit: 'N', value: data.rollingResistanceA.value }, diff --git a/front/src/modules/simulationResult/SimulationResultExport/SimulationResultsExport.tsx b/front/src/modules/simulationResult/SimulationResultExport/SimulationResultsExport.tsx index 2c4647586a9..007dc287caa 100644 --- a/front/src/modules/simulationResult/SimulationResultExport/SimulationResultsExport.tsx +++ b/front/src/modules/simulationResult/SimulationResultExport/SimulationResultsExport.tsx @@ -71,7 +71,7 @@ const SimulationResultExport = ({ > {({ url }) => (