Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

refactor(nuxt): enable strict type checking #6368

Merged
merged 21 commits into from
Aug 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/kit/src/loader/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { NuxtConfigSchema } from '@nuxt/schema'
export interface LoadNuxtConfigOptions extends LoadConfigOptions<NuxtConfig> {}

export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise<NuxtOptions> {
const { config: nuxtConfig, configFile, layers, cwd } = await loadConfig({
const { config: nuxtConfig, configFile, layers, cwd } = await loadConfig<NuxtConfig>({
name: 'nuxt',
configFile: 'nuxt.config',
rcFile: '.nuxtrc',
Expand All @@ -23,6 +23,7 @@ export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise<Nuxt

// Resolve `rootDir` & `srcDir` of layers
for (const layer of layers) {
layer.config = layer.config || {}
layer.config.rootDir = layer.config.rootDir ?? layer.cwd
layer.config.srcDir = resolve(layer.config.rootDir, layer.config.srcDir)
}
Expand Down
10 changes: 5 additions & 5 deletions packages/nuxt/src/app/compat/capi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ export * from 'vue'

export const install = () => {}

export function set (target, key, val) {
export function set (target: any, key: string | number | symbol, val: any) {
if (Array.isArray(target)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, val)
target.length = Math.max(target.length, key as number)
target.splice(key as number, 1, val)
return val
}
target[key] = val
return val
}

export function del (target, key) {
export function del (target: any, key: string | number | symbol) {
if (Array.isArray(target)) {
target.splice(key, 1)
target.splice(key as number, 1)
return
}
delete target[key]
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/components/nuxt-error-boundary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default defineComponent({
}
},
setup (_props, { slots, emit }) {
const error = ref(null)
const error = ref<Error | null>(null)
const nuxtApp = useNuxtApp()

onErrorCaptured((err) => {
Expand Down
24 changes: 13 additions & 11 deletions packages/nuxt/src/app/components/nuxt-link.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { defineComponent, h, resolveComponent, PropType, computed, DefineComponent } from 'vue'
import { RouteLocationRaw, Router } from 'vue-router'
import { defineComponent, h, resolveComponent, PropType, computed, DefineComponent, ComputedRef } from 'vue'
import { RouteLocationRaw } from 'vue-router'
import { hasProtocol } from 'ufo'

import { navigateTo, useRouter } from '#app'

const firstNonUndefined = <T>(...args: T[]): T => args.find(arg => arg !== undefined)
const firstNonUndefined = <T>(...args: (T | undefined)[]) => args.find(arg => arg !== undefined)

const DEFAULT_EXTERNAL_REL_ATTRIBUTE = 'noopener noreferrer'

Expand All @@ -24,8 +24,8 @@ export type NuxtLinkProps = {
custom?: boolean

// Attributes
target?: string
rel?: string
target?: string | null
rel?: string | null
noRel?: boolean

// Styling
Expand All @@ -39,7 +39,7 @@ export type NuxtLinkProps = {
export function defineNuxtLink (options: NuxtLinkOptions) {
const componentName = options.componentName || 'NuxtLink'

const checkPropConflicts = (props: NuxtLinkProps, main: string, sub: string): void => {
const checkPropConflicts = (props: NuxtLinkProps, main: keyof NuxtLinkProps, sub: keyof NuxtLinkProps): void => {
if (process.dev && props[main] !== undefined && props[sub] !== undefined) {
console.warn(`[${componentName}] \`${main}\` and \`${sub}\` cannot be used together. \`${sub}\` will be ignored.`)
}
Expand Down Expand Up @@ -116,18 +116,18 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
}
},
setup (props, { slots }) {
const router = useRouter() as Router | undefined
const router = useRouter()

// Resolving `to` value from `to` and `href` props
const to = computed<string | RouteLocationRaw>(() => {
const to: ComputedRef<string | RouteLocationRaw> = computed(() => {
checkPropConflicts(props, 'to', 'href')

return props.to || props.href || '' // Defaults to empty string (won't render any `href` attribute)
})

// Resolving link type
const isExternal = computed<boolean>(() => {
// External prop is explictly set
// External prop is explicitly set
if (props.external) {
return true
}
Expand Down Expand Up @@ -180,11 +180,13 @@ export function defineNuxtLink (options: NuxtLinkOptions) {

// https://router.vuejs.org/api/#custom
if (props.custom) {
if (!slots.default) { return null }
if (!slots.default) {
return null
}
return slots.default({
href,
navigate,
route: router.resolve(href),
route: router.resolve(href!),
rel,
target,
isActive: false,
Expand Down
6 changes: 3 additions & 3 deletions packages/nuxt/src/app/components/utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { h } from 'vue'
import { defineComponent, h } from 'vue'
import type { Component } from 'vue'

const Fragment = {
const Fragment = defineComponent({
setup (_props, { slots }) {
return () => slots.default?.()
}
}
})

/**
* Internal utility
Expand Down
20 changes: 10 additions & 10 deletions packages/nuxt/src/app/composables/asyncData.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { onBeforeMount, onServerPrefetch, onUnmounted, ref, getCurrentInstance, watch, unref } from 'vue'
import type { Ref, WatchSource } from 'vue'
import { wrapInRef } from './utils'
import { NuxtApp, useNuxtApp } from '#app'

export type _Transform<Input = any, Output = any> = (input: Input) => Output
Expand All @@ -25,7 +24,7 @@ export interface AsyncDataOptions<
> {
server?: boolean
lazy?: boolean
default?: () => DataT | Ref<DataT>
default?: () => DataT | Ref<DataT> | null
transform?: Transform
pick?: PickKeys
watch?: MultiWatchSources
Expand All @@ -37,10 +36,10 @@ export interface RefreshOptions {
}

export interface _AsyncData<DataT, ErrorT> {
data: Ref<DataT>
data: Ref<DataT | null>
pending: Ref<boolean>
refresh: (opts?: RefreshOptions) => Promise<void>
error: Ref<ErrorT>
error: Ref<ErrorT | null>
}

export type AsyncData<Data, Error> = _AsyncData<Data, Error> & Promise<_AsyncData<Data, Error>>
Expand Down Expand Up @@ -70,7 +69,7 @@ export function useAsyncData<
DataE = Error,
Transform extends _Transform<DataT> = _Transform<DataT, DataT>,
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
> (...args): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null | true> {
> (...args: any[]): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null | true> {
const autoKey = typeof args[args.length - 1] === 'string' ? args.pop() : undefined
if (typeof args[0] !== 'string') { args.unshift(autoKey) }

Expand Down Expand Up @@ -102,7 +101,8 @@ export function useAsyncData<
// Setup hook callbacks once per instance
const instance = getCurrentInstance()
if (instance && !instance._nuxtOnBeforeMountCbs) {
const cbs = instance._nuxtOnBeforeMountCbs = []
instance._nuxtOnBeforeMountCbs = []
const cbs = instance._nuxtOnBeforeMountCbs
if (instance && process.client) {
onBeforeMount(() => {
cbs.forEach((cb) => { cb() })
Expand All @@ -115,7 +115,7 @@ export function useAsyncData<
const useInitialCache = () => options.initialCache && nuxt.payload.data[key] !== undefined

const asyncData = {
data: wrapInRef(nuxt.payload.data[key] ?? options.default()),
data: ref(nuxt.payload.data[key] ?? options.default?.() ?? null),
pending: ref(!useInitialCache()),
error: ref(nuxt.payload._errors[key] ?? null)
} as AsyncData<DataT, DataE>
Expand Down Expand Up @@ -151,7 +151,7 @@ export function useAsyncData<
})
.catch((error: any) => {
asyncData.error.value = error
asyncData.data.value = unref(options.default())
asyncData.data.value = unref(options.default?.() ?? null)
})
.finally(() => {
asyncData.pending.value = false
Expand Down Expand Up @@ -230,7 +230,7 @@ export function useLazyAsyncData<
DataE = Error,
Transform extends _Transform<DataT> = _Transform<DataT, DataT>,
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
> (...args): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null | true> {
> (...args: any[]): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null | true> {
const autoKey = typeof args[args.length - 1] === 'string' ? args.pop() : undefined
if (typeof args[0] !== 'string') { args.unshift(autoKey) }
const [key, handler, options] = args as [string, (ctx?: NuxtApp) => Promise<DataT>, AsyncDataOptions<DataT, Transform, PickKeys>]
Expand All @@ -249,7 +249,7 @@ export function refreshNuxtData (keys?: string | string[]): Promise<void> {
function pick (obj: Record<string, any>, keys: string[]) {
const newObj = {}
for (const key of keys) {
newObj[key] = obj[key]
(newObj as any)[key] = obj[key]
}
return newObj
}
8 changes: 3 additions & 5 deletions packages/nuxt/src/app/composables/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export const NuxtComponentIndicator = '__nuxt_component'
async function runLegacyAsyncData (res: Record<string, any> | Promise<Record<string, any>>, fn: (nuxtApp: NuxtApp) => Promise<Record<string, any>>) {
const nuxt = useNuxtApp()
const route = useRoute()
const vm = getCurrentInstance()
const { fetchKey } = vm.proxy.$options
const vm = getCurrentInstance()!
const { fetchKey } = vm.proxy!.$options
const key = typeof fetchKey === 'function' ? fetchKey(() => '') : fetchKey || route.fullPath
const { data } = await useAsyncData(`options:asyncdata:${key}`, () => fn(nuxt))
if (data.value && typeof data.value === 'object') {
Expand Down Expand Up @@ -38,8 +38,7 @@ export const defineNuxtComponent: typeof defineComponent =
setup (props, ctx) {
const res = setup?.(props, ctx) || {}

let promises: unknown[] | undefined = []
promises = promises || []
const promises: Promise<any>[] = []
if (options.asyncData) {
promises.push(runLegacyAsyncData(res, options.asyncData))
}
Expand All @@ -49,7 +48,6 @@ export const defineNuxtComponent: typeof defineComponent =
.then(() => res)
.finally(() => {
promises.length = 0
promises = null
})
}
} as DefineComponent
Expand Down
11 changes: 5 additions & 6 deletions packages/nuxt/src/app/composables/cookie.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Ref, watch } from 'vue'
import { ref, Ref, watch } from 'vue'
import { parse, serialize, CookieParseOptions, CookieSerializeOptions } from 'cookie-es'
import { appendHeader } from 'h3'
import type { CompatibilityEvent } from 'h3'
import destr from 'destr'
import { isEqual } from 'ohash'
import { useRequestEvent } from './ssr'
import { wrapInRef } from './utils'
import { useNuxtApp } from '#app'

type _CookieOptions = Omit<CookieSerializeOptions & CookieParseOptions, 'decode' | 'encode'>
Expand All @@ -24,11 +23,11 @@ const CookieDefaults: CookieOptions<any> = {
encode: val => encodeURIComponent(typeof val === 'string' ? val : JSON.stringify(val))
}

export function useCookie <T=string> (name: string, _opts?: CookieOptions<T>): CookieRef<T> {
export function useCookie <T = string> (name: string, _opts?: CookieOptions<T>): CookieRef<T> {
const opts = { ...CookieDefaults, ..._opts }
const cookies = readRawCookies(opts)
const cookies = readRawCookies(opts) || {}

const cookie = wrapInRef<T>(cookies[name] ?? opts.default?.())
const cookie = ref<T | undefined>(cookies[name] as any ?? opts.default?.())

if (process.client) {
watch(cookie, () => { writeClientCookie(name, cookie.value, opts as CookieSerializeOptions) })
Expand All @@ -46,7 +45,7 @@ export function useCookie <T=string> (name: string, _opts?: CookieOptions<T>): C
return cookie as CookieRef<T>
}

function readRawCookies (opts: CookieOptions = {}): Record<string, string> {
function readRawCookies (opts: CookieOptions = {}): Record<string, string> | undefined {
if (process.server) {
return parse(useRequestEvent()?.req.headers.cookie || '', opts)
} else if (process.client) {
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/composables/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function useFetch<
arg1?: string | UseFetchOptions<_ResT, Transform, PickKeys>,
arg2?: string
) {
const [opts, autoKey] = typeof arg1 === 'string' ? [{}, arg1] : [arg1, arg2]
const [opts = {}, autoKey] = typeof arg1 === 'string' ? [{}, arg1] : [arg1, arg2]
const _key = opts.key || autoKey
if (!_key || typeof _key !== 'string') {
throw new TypeError('[nuxt] [useFetch] key must be a string: ' + _key)
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/app/composables/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export interface NavigateToOptions {
redirectCode?: number
}

export const navigateTo = (to: RouteLocationRaw, options: NavigateToOptions = {}): Promise<void | NavigationFailure> | RouteLocationRaw => {
export const navigateTo = (to: RouteLocationRaw | undefined | null, options: NavigateToOptions = {}): Promise<void | NavigationFailure> | RouteLocationRaw => {
if (!to) {
to = '/'
}
Expand All @@ -74,7 +74,7 @@ export const navigateTo = (to: RouteLocationRaw, options: NavigateToOptions = {}
const nuxtApp = useNuxtApp()
if (nuxtApp.ssrContext && nuxtApp.ssrContext.event) {
const redirectLocation = joinURL(useRuntimeConfig().app.baseURL, router.resolve(to).fullPath || '/')
return nuxtApp.callHook('app:redirected').then(() => sendRedirect(nuxtApp.ssrContext.event, redirectLocation, options.redirectCode || 302))
return nuxtApp.callHook('app:redirected').then(() => sendRedirect(nuxtApp.ssrContext!.event, redirectLocation, options.redirectCode || 302))
}
}
// Client-side redirection using vue-router
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/app/composables/ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { NuxtApp } from '#app/nuxt'

export function useRequestHeaders<K extends string = string> (include: K[]): Record<K, string | undefined>
export function useRequestHeaders (): Readonly<Record<string, string | undefined>>
export function useRequestHeaders (include?) {
export function useRequestHeaders (include?: any[]) {
if (process.client) { return {} }
const headers: Record<string, string | string[]> = useNuxtApp().ssrContext?.event.req.headers ?? {}
const headers = useNuxtApp().ssrContext?.event.req.headers ?? {}
if (!include) { return headers }
return Object.fromEntries(include.filter(key => headers[key]).map(key => [key, headers[key]]))
}
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/composables/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useNuxtApp } from '#app'
*/
export function useState <T> (key?: string, init?: (() => T | Ref<T>)): Ref<T>
export function useState <T> (init?: (() => T | Ref<T>)): Ref<T>
export function useState <T> (...args): Ref<T> {
export function useState <T> (...args: any): Ref<T> {
const autoKey = typeof args[args.length - 1] === 'string' ? args.pop() : undefined
if (typeof args[0] !== 'string') { args.unshift(autoKey) }
const [_key, init] = args as [string, (() => T | Ref<T>)]
Expand Down
3 changes: 0 additions & 3 deletions packages/nuxt/src/app/composables/utils.ts

This file was deleted.

8 changes: 4 additions & 4 deletions packages/nuxt/src/app/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ if (process.server) {
await nuxt.hooks.callHook('app:created', vueApp)
} catch (err) {
await nuxt.callHook('app:error', err)
nuxt.payload.error = nuxt.payload.error || err
nuxt.payload.error = (nuxt.payload.error || err) as any
}

return vueApp
Expand Down Expand Up @@ -66,7 +66,7 @@ if (process.client) {
await applyPlugins(nuxt, plugins)
} catch (err) {
await nuxt.callHook('app:error', err)
nuxt.payload.error = nuxt.payload.error || err
nuxt.payload.error = (nuxt.payload.error || err) as any
}

try {
Expand All @@ -77,11 +77,11 @@ if (process.client) {
await nextTick()
} catch (err) {
await nuxt.callHook('app:error', err)
nuxt.payload.error = nuxt.payload.error || err
nuxt.payload.error = (nuxt.payload.error || err) as any
}
}

entry().catch((error) => {
entry().catch((error: unknown) => {
console.error('Error while mounting app:', error) // eslint-disable-line no-console
})
}
Expand Down
Loading