Repository: nuxt/nuxt
File: packages/nuxt/src/pages/module.ts (TypeScript)

Code before:
          '  }',
          '}',
        ].join('\n')
      },
    }, { nuxt: true, nitro: true, node: true })

    addTypeTemplate({
      filename: 'types/layouts.d.ts',
      getContents: ({ app }) => {
        return [
          'import type { ComputedRef, MaybeRef } from \'vue\'',
          '',
          'type ComponentProps<T> = T extends new(...args: any) => { $props: infer P } ? NonNullable<P>',
          '  : T extends (props: infer P, ...args: any) => any ? P',
          '  : {}',
          '',
          'declare module \'nuxt/app\' {',
          '  interface NuxtLayouts {',
          ...Object.values(app.layouts).map(layout => `    ${genObjectKey(layout.name)}: ComponentProps<${genInlineTypeImport(layout.file)}>,`),
          '}',
          '  export type LayoutKey = keyof NuxtLayouts extends never ? string : keyof NuxtLayouts',
          '  interface PageMeta {',
          '    layout?: MaybeRef<LayoutKey | false> | ComputedRef<LayoutKey | false> | {',
          '      name?: MaybeRef<LayoutKey | false> | ComputedRef<LayoutKey | false>',
          '      props?: Record<string, any>',
          '    }',
          '  }',
          '}',
        ].join('\n')
      },
    })

    // add page meta types if enabled
    if (nuxt.options.experimental.viewTransition) {
      addTypeTemplate({
        filename: 'types/view-transitions.d.ts',
        getContents: () => {
          return [
            'declare module \'nuxt/app\' {',
            '  interface PageMeta {',
            '    viewTransition?: boolean | \'always\'',
            '  }',
            '}',
            'export {}',
          ].join('\n')
        },
      })
    }

    // Add <NuxtPage>
    addComponent({

Review comment (suggestion):
It seems hard to type the props. I think it could be done with a vls plugin (in dxup), but that would limit its widespread adoption.

Code after:
          '  }',
          '}',
        ].join('\n')
      },
    }, { nuxt: true, nitro: true, node: true })

    addTypeTemplate({
      filename: 'types/layouts.d.ts',
      getContents: ({ app }) => {
        return [
          'import type { ComputedRef, MaybeRef } from \'vue\'',
          '',
          'type ComponentProps<T> = T extends new(...args: any) => { $props: infer P } ? NonNullable<P>',
          '  : T extends (props: infer P, ...args: any) => any ? P',
          '  : {}',
          '',
          'declare module \'nuxt/app\' {',
          '  interface NuxtLayouts {',
          ...Object.values(app.layouts).map(layout => `    ${genObjectKey(layout.name)}: ComponentProps<${genInlineTypeImport(layout.file)}>`),
          '  }',
          '  export type LayoutKey = keyof NuxtLayouts extends never ? string : keyof NuxtLayouts',
          '  interface PageMeta {',
          '    layout?: MaybeRef<LayoutKey | false> | ComputedRef<LayoutKey | false> | {',
          '      name?: MaybeRef<LayoutKey | false> | ComputedRef<LayoutKey | false>',
          '      props?: Record<string, any>',
          '    }',
          '  }',
          '}',
        ].join('\n')
      },
    })

    // add page meta types if enabled
    if (nuxt.options.experimental.viewTransition) {
      addTypeTemplate({
        filename: 'types/view-transitions.d.ts',
        getContents: () => {
          return [
            'declare module \'nuxt/app\' {',
            '  interface PageMeta {',
            '    viewTransition?: boolean | \'always\'',
            '  }',
            '}',
            'export {}',
          ].join('\n')
        },
      })
    }

    // Add <NuxtPage>
    addComponent({