import { routerKey, routeLocationKey } from './injectionSymbols'
import { RouteRecord } from './matcher/types'
import { NavigationFailure } from './errors'
-import { isBrowser, noop } from './utils'
+import { isArray, isBrowser, noop } from './utils'
import { RouterTyped } from './typedRouter'
export interface RouterLinkOptions {
if (innerValue !== outerValue) return false
} else {
if (
- !Array.isArray(outerValue) ||
+ !isArray(outerValue) ||
outerValue.length !== innerValue.length ||
innerValue.some((value, i) => value !== outerValue[i])
)
viewDepthKey,
routerViewLocationKey,
} from './injectionSymbols'
-import { assign, isBrowser } from './utils'
+import { assign, isArray, isBrowser } from './utils'
import { warn } from './warning'
import { isSameRouteRecord } from './location'
meta: matchedRoute.meta,
}
- const internalInstances = Array.isArray(component.ref)
+ const internalInstances = isArray(component.ref)
? component.ref.map(r => r.i)
: [component.ref.i]
import { UseLinkDevtoolsContext } from './RouterLink'
import { RouterViewDevtoolsContext } from './RouterView'
import { RouteLocationNormalized } from './types'
-import { assign } from './utils'
+import { assign, isArray } from './utils'
function formatRouteLocation(
routeLocation: RouteLocationNormalized,
})
}
// if multiple useLink are used
- if (Array.isArray(componentInstance.__vrl_devtools)) {
+ if (isArray(componentInstance.__vrl_devtools)) {
componentInstance.__devtoolsApi = api
;(
componentInstance.__vrl_devtools as UseLinkDevtoolsContext[]
} from './types'
import { RouteRecord } from './matcher/types'
import { warn } from './warning'
+import { isArray } from './utils'
/**
* Location object returned by {@link `parseURL`}.
a: RouteParamValue | readonly RouteParamValue[],
b: RouteParamValue | readonly RouteParamValue[]
): boolean {
- return Array.isArray(a)
+ return isArray(a)
? isEquivalentArray(a, b)
- : Array.isArray(b)
+ : isArray(b)
? isEquivalentArray(b, a)
: a === b
}
* @param a - array of values
* @param b - array of values or a single value
*/
-function isEquivalentArray<T>(a: T[], b: T[] | T): boolean {
- return Array.isArray(b)
+function isEquivalentArray<T>(a: readonly T[], b: readonly T[] | T): boolean {
+ return isArray(b)
? a.length === b.length && a.every((value, i) => value === b[i])
: a.length === 1 && a[0] === b
}
import { Token, TokenType } from './pathTokenizer'
-import { assign } from '../utils'
+import { assign, isArray } from '../utils'
export type PathParams = Record<string, string | readonly string[]>
const param: string | readonly string[] =
value in params ? params[value] : ''
- if (Array.isArray(param) && !repeatable)
+ if (isArray(param) && !repeatable) {
throw new Error(
`Provided param "${value}" is an array but it is not repeatable (* or + modifiers)`
)
- const text: string = Array.isArray(param)
+ }
+
+ const text: string = isArray(param)
? (param as string[]).join('/')
: (param as string)
if (!text) {
import { decode, encodeQueryKey, encodeQueryValue, PLUS_RE } from './encoding'
+import { isArray } from './utils'
/**
* Possible values in normalized {@link LocationQuery}. `null` renders the query
*/
export type LocationQuery = Record<
string,
- LocationQueryValue | LocationQueryValue[]
+ LocationQueryValue | readonly LocationQueryValue[]
>
/**
* Loose {@link LocationQuery} object that can be passed to functions like
*/
export type LocationQueryRaw = Record<
string | number,
- LocationQueryValueRaw | LocationQueryValueRaw[]
+ LocationQueryValueRaw | readonly LocationQueryValueRaw[]
>
/**
if (key in query) {
// an extra variable for ts types
let currentValue = query[key]
- if (!Array.isArray(currentValue)) {
+ if (!isArray(currentValue)) {
currentValue = query[key] = [currentValue]
}
- currentValue.push(value)
+ // we force the modification
+ ;(currentValue as LocationQueryValue[]).push(value)
} else {
query[key] = value
}
continue
}
// keep null values
- const values: LocationQueryValueRaw[] = Array.isArray(value)
+ const values: LocationQueryValueRaw[] = isArray(value)
? value.map(v => v && encodeQueryValue(v))
: [value && encodeQueryValue(value)]
for (const key in query) {
const value = query[key]
if (value !== undefined) {
- normalizedQuery[key] = Array.isArray(value)
+ normalizedQuery[key] = isArray(value)
? value.map(v => (v == null ? null : '' + v))
: value == null
? value
NavigationRedirectError,
isNavigationFailure,
} from './errors'
-import { applyToParams, isBrowser, assign, noop } from './utils'
+import { applyToParams, isBrowser, assign, noop, isArray } from './utils'
import { useCallbacks } from './utils/callbacks'
import { encodeParam, decode, encodeHash } from './encoding'
import {
for (const record of to.matched) {
// do not trigger beforeEnter on reused views
if (record.beforeEnter && !from.matched.includes(record)) {
- if (Array.isArray(record.beforeEnter)) {
+ if (isArray(record.beforeEnter)) {
for (const beforeEnter of record.beforeEnter)
guards.push(guardToPromiseFn(beforeEnter, to, from))
} else {
for (const key in params) {
const value = params[key]
- newParams[key] = Array.isArray(value)
+ newParams[key] = isArray(value)
? value.map(fn)
: fn(value as Exclude<RouteParamValueRaw, any[]>)
}
}
export const noop = () => {}
+
+/**
+ * Typesafe alternative to Array.isArray
+ * https://github.com/microsoft/TypeScript/pull/48228
+ */
+export const isArray: (arg: ArrayLike<any> | any) => arg is ReadonlyArray<any> =
+ Array.isArray