Skip to content

Commit 4f6e77f

Browse files
committedMar 7, 2025·
refactor: explicit number casting
1 parent c1a0bb1 commit 4f6e77f

File tree

20 files changed

+54
-48
lines changed

20 files changed

+54
-48
lines changed
 

‎.eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ module.exports = {
8585
ignoreCase: true,
8686
}],
8787
'multiline-ternary': 'off',
88+
'no-implicit-coercion': ['error', { boolean: false }],
8889

8990
'sonarjs/cognitive-complexity': 'off',
9091
'sonarjs/no-duplicate-string': 'off',

‎packages/docs/src/App.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@
125125
document.body.append(copy)
126126
127127
;(copy.querySelectorAll('[data-scroll-x], [data-scroll-y]') as NodeListOf<HTMLElement>).forEach(el => {
128-
el.scrollLeft = +el.dataset.scrollX!
129-
el.scrollTop = +el.dataset.scrollY!
128+
el.scrollLeft = Number(el.dataset.scrollX)
129+
el.scrollTop = Number(el.dataset.scrollY)
130130
})
131131
132132
function onTransitionend (e: TransitionEvent) {

‎packages/vuetify/src/components/VBadge/VBadge.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,16 @@ export const VBadge = genericComponent<VBadgeSlots>()({
7373
: (props.dot ? 8 : 12)
7474

7575
return base + (
76-
['top', 'bottom'].includes(side) ? +(props.offsetY ?? 0)
77-
: ['left', 'right'].includes(side) ? +(props.offsetX ?? 0)
76+
['top', 'bottom'].includes(side) ? Number(props.offsetY ?? 0)
77+
: ['left', 'right'].includes(side) ? Number(props.offsetX ?? 0)
7878
: 0
7979
)
8080
})
8181

8282
useRender(() => {
8383
const value = Number(props.content)
8484
const content = (!props.max || isNaN(value)) ? props.content
85-
: value <= +props.max ? value
85+
: value <= Number(props.max) ? value
8686
: `${props.max}+`
8787

8888
const [badgeAttrs, attrs] = pickWithRest(ctx.attrs as Record<string, any>, [

‎packages/vuetify/src/components/VCarousel/VCarousel.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ export const VCarousel = genericComponent<new <T>(
9494
function startTimeout () {
9595
if (!props.cycle || !windowRef.value) return
9696

97-
slideTimeout = window.setTimeout(windowRef.value.group.next, +props.interval > 0 ? +props.interval : 6000)
97+
slideTimeout = window.setTimeout(
98+
windowRef.value.group.next,
99+
Number(props.interval) > 0 ? Number(props.interval) : 6000
100+
)
98101
}
99102

100103
function restartTimeout () {

‎packages/vuetify/src/components/VDataTable/composables/headers.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ function parseFixedColumns (items: InternalDataTableHeader[]) {
115115
} else {
116116
if (!seenFixed) {
117117
item.lastFixed = true
118-
} else if (isNaN(+item.width!)) {
118+
} else if (isNaN(Number(item.width))) {
119119
consoleError(`Multiple fixed columns should have a static width (key: ${item.key})`)
120120
} else {
121-
item.minWidth = Math.max(+item.width! || 0, +item.minWidth! || 0)
121+
item.minWidth = Math.max(Number(item.width) || 0, Number(item.minWidth) || 0)
122122
}
123123
seenFixed = true
124124
}

‎packages/vuetify/src/components/VDataTable/composables/paginate.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ type PaginationProps = {
4343
}
4444

4545
export function createPagination (props: PaginationProps) {
46-
const page = useProxiedModel(props, 'page', undefined, value => +(value ?? 1))
47-
const itemsPerPage = useProxiedModel(props, 'itemsPerPage', undefined, value => +(value ?? 10))
46+
const page = useProxiedModel(props, 'page', undefined, value => Number(value ?? 1))
47+
const itemsPerPage = useProxiedModel(props, 'itemsPerPage', undefined, value => Number(value ?? 10))
4848

4949
return { page, itemsPerPage }
5050
}

‎packages/vuetify/src/components/VPagination/VPagination.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ export const VPagination = genericComponent<VPaginationSlots>()({
183183
const minButtons = props.showFirstLastPage ? 5 : 3
184184
return Math.max(0, Math.floor(
185185
// Round to two decimal places to avoid floating point errors
186-
+((totalWidth - itemWidth * minButtons) / itemWidth).toFixed(2)
186+
Number(((totalWidth - itemWidth * minButtons) / itemWidth).toFixed(2))
187187
))
188188
}
189189

@@ -262,7 +262,7 @@ export const VPagination = genericComponent<VPaginationSlots>()({
262262
ref,
263263
ellipsis: false,
264264
icon: true,
265-
disabled: !!props.disabled || +props.length < 2,
265+
disabled: !!props.disabled || Number(props.length) < 2,
266266
color: isActive ? props.activeColor : props.color,
267267
'aria-current': isActive,
268268
'aria-label': t(isActive ? props.currentPageAriaLabel : props.pageAriaLabel, item),
@@ -315,7 +315,7 @@ export const VPagination = genericComponent<VPaginationSlots>()({
315315
}
316316

317317
function onKeydown (e: KeyboardEvent) {
318-
if (e.key === keyValues.left && !props.disabled && page.value > +props.start) {
318+
if (e.key === keyValues.left && !props.disabled && page.value > Number(props.start)) {
319319
page.value = page.value - 1
320320
nextTick(updateFocus)
321321
} else if (e.key === keyValues.right && !props.disabled && page.value < start.value + length.value - 1) {

‎packages/vuetify/src/components/VParallax/VParallax.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export const VParallax = genericComponent<VImgSlots>()({
6666
watch(() => contentRect.value?.height, onScroll)
6767

6868
const scale = computed(() => {
69-
return 1 - clamp(+props.scale)
69+
return 1 - clamp(Number(props.scale))
7070
})
7171

7272
let frame = -1

‎packages/vuetify/src/components/VRating/VRating.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export const VRating = genericComponent<VRatingSlots>()({
101101
const { t } = useLocale()
102102
const { themeClasses } = provideTheme(props)
103103
const rating = useProxiedModel(props, 'modelValue')
104-
const normalizedValue = computed(() => clamp(parseFloat(rating.value), 0, +props.length))
104+
const normalizedValue = computed(() => clamp(parseFloat(rating.value), 0, Number(props.length)))
105105

106106
const range = computed(() => createRange(Number(props.length), 1))
107107
const increments = computed(() => range.value.flatMap(v => props.halfIncrements ? [v - 0.5, v] : [v]))

‎packages/vuetify/src/components/VSlider/slider.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ type SliderData = {
149149
export const useSteps = (props: SliderProps) => {
150150
const min = computed(() => parseFloat(props.min))
151151
const max = computed(() => parseFloat(props.max))
152-
const step = computed(() => +props.step > 0 ? parseFloat(props.step) : 0)
152+
const step = computed(() => Number(props.step) > 0 ? parseFloat(props.step) : 0)
153153
const decimals = computed(() => Math.max(getDecimals(step.value), getDecimals(min.value)))
154154

155155
function roundValue (value: string | number) {

‎packages/vuetify/src/components/VSparkline/VBarline.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export const VBarline = genericComponent<VBarlineSlots>()({
9090
return {
9191
x: minX + index * gridX,
9292
y: horizonY - height +
93-
+(value < 0) * height,
93+
Number(value < 0) * height,
9494
height,
9595
value,
9696
}

‎packages/vuetify/src/components/VTextarea/VTextarea.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,10 @@ export const VTextarea = genericComponent<VTextareaSlots>()({
150150
}
151151

152152
const sizerRef = ref<HTMLTextAreaElement>()
153-
const rows = ref(+props.rows)
153+
const rows = ref(Number(props.rows))
154154
const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant))
155155
watchEffect(() => {
156-
if (!props.autoGrow) rows.value = +props.rows
156+
if (!props.autoGrow) rows.value = Number(props.rows)
157157
})
158158
function calculateInputHeight () {
159159
if (!props.autoGrow) return

‎packages/vuetify/src/composables/stack.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ export function useStack (
3030
})
3131
provide(StackSymbol, stack)
3232

33-
const _zIndex = shallowRef(+zIndex.value)
33+
const _zIndex = shallowRef(Number(zIndex.value))
3434
useToggleScope(isActive, () => {
3535
const lastZIndex = globalStack.at(-1)?.[1]
36-
_zIndex.value = lastZIndex ? lastZIndex + 10 : +zIndex.value
36+
_zIndex.value = lastZIndex ? lastZIndex + 10 : Number(zIndex.value)
3737

3838
if (createStackEntry) {
3939
globalStack.push([vm.uid, _zIndex.value])

‎packages/vuetify/src/composables/validation.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export function useValidation (
9292
))
9393
const errorMessages = computed(() => {
9494
return props.errorMessages?.length
95-
? wrapInArray(props.errorMessages).concat(internalErrorMessages.value).slice(0, Math.max(0, +props.maxErrors))
95+
? wrapInArray(props.errorMessages).concat(internalErrorMessages.value).slice(0, Math.max(0, Number(props.maxErrors)))
9696
: internalErrorMessages.value
9797
})
9898
const validateOn = computed(() => {
@@ -197,7 +197,7 @@ export function useValidation (
197197
isValidating.value = true
198198

199199
for (const rule of props.rules) {
200-
if (results.length >= +(props.maxErrors ?? 1)) {
200+
if (results.length >= Number(props.maxErrors ?? 1)) {
201201
break
202202
}
203203

‎packages/vuetify/src/labs/VNumberInput/VNumberInput.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export const VNumberInput = genericComponent<VNumberInputSlots>()({
9999
val => val ?? null,
100100
val => val == null
101101
? val ?? null
102-
: clamp(+val, props.min, props.max)
102+
: clamp(Number(val), props.min, props.max)
103103
)
104104

105105
const _inputText = shallowRef<string | null>(null)
@@ -118,8 +118,8 @@ export const VNumberInput = genericComponent<VNumberInputSlots>()({
118118
if (val === null || val === '') {
119119
model.value = null
120120
_inputText.value = null
121-
} else if (!isNaN(+val) && +val <= props.max && +val >= props.min) {
122-
model.value = +val
121+
} else if (!isNaN(Number(val)) && Number(val) <= props.max && Number(val) >= props.min) {
122+
model.value = Number(val)
123123
_inputText.value = val
124124
}
125125
},
@@ -266,8 +266,8 @@ export const VNumberInput = genericComponent<VNumberInputSlots>()({
266266
if (controlsDisabled.value) return
267267
if (!vTextFieldRef.value) return
268268
const actualText = vTextFieldRef.value.value
269-
if (actualText && !isNaN(+actualText)) {
270-
inputText.value = correctPrecision(clamp(+actualText, props.min, props.max))
269+
if (actualText && !isNaN(Number(actualText))) {
270+
inputText.value = correctPrecision(clamp(Number(actualText), props.min, props.max))
271271
} else {
272272
inputText.value = null
273273
}

‎packages/vuetify/src/labs/VTimePicker/VTimePicker.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ export const VTimePicker = genericComponent<VTimePickerSlots>()({
9595
const maxHour = props.max ? Number(props.max.split(':')[0]) : 23
9696

9797
return (val: number) => {
98-
return val >= minHour * 1 &&
99-
val <= maxHour * 1 &&
98+
return val >= Number(minHour) &&
99+
val <= Number(maxHour) &&
100100
(!cb || cb(val))
101101
}
102102
})
@@ -117,8 +117,8 @@ export const VTimePicker = genericComponent<VTimePickerSlots>()({
117117

118118
const [minHour, minMinute] = props.min ? props.min.split(':').map(Number) : [0, 0]
119119
const [maxHour, maxMinute] = props.max ? props.max.split(':').map(Number) : [23, 59]
120-
const minTime = minHour * 60 + minMinute * 1
121-
const maxTime = maxHour * 60 + maxMinute * 1
120+
const minTime = minHour * 60 + Number(minMinute)
121+
const maxTime = maxHour * 60 + Number(maxMinute)
122122

123123
return (val: number) => {
124124
const time = 60 * inputHour.value! + val
@@ -151,8 +151,8 @@ export const VTimePicker = genericComponent<VTimePickerSlots>()({
151151

152152
const [minHour, minMinute, minSecond] = props.min ? props.min.split(':').map(Number) : [0, 0, 0]
153153
const [maxHour, maxMinute, maxSecond] = props.max ? props.max.split(':').map(Number) : [23, 59, 59]
154-
const minTime = minHour * 3600 + minMinute * 60 + (minSecond || 0) * 1
155-
const maxTime = maxHour * 3600 + maxMinute * 60 + (maxSecond || 0) * 1
154+
const minTime = minHour * 3600 + minMinute * 60 + Number(minSecond || 0)
155+
const maxTime = maxHour * 3600 + maxMinute * 60 + Number(maxSecond || 0)
156156

157157
return (val: number) => {
158158
const time = 3600 * inputHour.value! + 60 * inputMinute.value! + val

‎packages/vuetify/src/locale/adapters/vuetify.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const LANG_PREFIX = '$vuetify.'
1616

1717
const replace = (str: string, params: unknown[]) => {
1818
return str.replace(/\{(\d+)\}/g, (match: string, index: string) => {
19-
return String(params[+index])
19+
return String(params[Number(index)])
2020
})
2121
}
2222

‎packages/vuetify/src/util/__tests__/helpers.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ describe('helpers', () => {
190190
expect(getPropertyFromItem(obj, 'c.0')).toBe(2)
191191
expect(getPropertyFromItem(obj, 'c.2.d')).toBe('d')
192192
expect(getPropertyFromItem(obj, 'c.2.d.x', 'fallback')).toBe('fallback')
193-
expect(getPropertyFromItem(obj, o => +o.a.b + +o.c[0])).toBe(3)
193+
expect(getPropertyFromItem(obj, o => Number(o.a.b) + Number(o.c[0]))).toBe(3)
194194
expect(getPropertyFromItem(obj, ['c', 2, 'd'])).toBe('d')
195195
expect(getPropertyFromItem(obj, 'x.y')).toBe('comp')
196196
expect(getPropertyFromItem(obj, ['x', 'y'])).toBe('nested')

‎packages/vuetify/src/util/animation.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ export function nullifyTransforms (el: HTMLElement): Box {
1111
let ta, sx, sy, dx, dy
1212
if (tx.startsWith('matrix3d(')) {
1313
ta = tx.slice(9, -1).split(/, /)
14-
sx = +ta[0]
15-
sy = +ta[5]
16-
dx = +ta[12]
17-
dy = +ta[13]
14+
sx = Number(ta[0])
15+
sy = Number(ta[5])
16+
dx = Number(ta[12])
17+
dy = Number(ta[13])
1818
} else if (tx.startsWith('matrix(')) {
1919
ta = tx.slice(7, -1).split(/, /)
20-
sx = +ta[0]
21-
sy = +ta[3]
22-
dx = +ta[4]
23-
dy = +ta[5]
20+
sx = Number(ta[0])
21+
sy = Number(ta[3])
22+
dx = Number(ta[4])
23+
dy = Number(ta[5])
2424
} else {
2525
return new Box(rect)
2626
}

‎packages/vuetify/src/util/helpers.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export function createRange (length: number, start = 0): number[] {
111111
export function getZIndex (el?: Element | null): number {
112112
if (!el || el.nodeType !== Node.ELEMENT_NODE) return 0
113113

114-
const index = +window.getComputedStyle(el).getPropertyValue('z-index')
114+
const index = Number(window.getComputedStyle(el).getPropertyValue('z-index'))
115115

116116
if (!index) return getZIndex(el.parentNode as Element)
117117
return index
@@ -122,12 +122,14 @@ export function convertToUnit (str: string | number | null | undefined, unit?: s
122122
export function convertToUnit (str: string | number | null | undefined, unit = 'px'): string | undefined {
123123
if (str == null || str === '') {
124124
return undefined
125-
} else if (isNaN(+str!)) {
125+
}
126+
const num = Number(str)
127+
if (isNaN(num)) {
126128
return String(str)
127-
} else if (!isFinite(+str!)) {
129+
} else if (!isFinite(num)) {
128130
return undefined
129131
} else {
130-
return `${Number(str)}${unit}`
132+
return `${num}${unit}`
131133
}
132134
}
133135

0 commit comments

Comments
 (0)
Please sign in to comment.