typescriptnext.jserror-handlingdeploymentsyntax-error

String is not assign to type Never error in NextJs


'use client'

import { FieldErrors, FieldValues, UseFormRegister } from "react-hook-form";
import { BiDollar } from "react-icons/bi";

interface InputProps {
    id: string;
    label: string;
    type?: string;
    disabled?: boolean;
    formatPrice?: boolean;
    required: boolean;
    register: UseFormRegister<FieldValues>;
    errors: FieldErrors;
}

const Input: React.FC<InputProps> = ({
    id,
    label,
    type = 'text',
    disabled,
    formatPrice,
    required,
    register,
    errors
}) => {
    return (
        <div className="w-full relative">
            {formatPrice && (
                <BiDollar
                    size={24}
                    className="text-neutral-700
                    absolute
                    top-5
                    left-2
                    "
                />
            )}
            <input
                id={id}
                disabled={disabled}
                {...register(id, { required })}
                placeholder=""
                type={type}
                className={`
                peer 
                w-full 
                p-4 
                pt-6 
                font-light
                 bg-white border-2 
                 rounded-md 
                 outline-none 
                 transition 
                 disabled:opacity-70
                 disabled:cursor-not-allowed
                 ${formatPrice ? 'pl-9' : 'pl-4'}
                 ${errors[id] ? 'border-rose-500' : 'border-neutral-300'}
                 ${errors[id] ? 'focus:border-rose-500' : 'focus:border-neutral-300'}`
                }
            />
            <label
                className={
                    `
                absolute
                text-base
                duration-150
                transform
                -translate-y-3
                top-5
                origin-[0]
                ${formatPrice ? 'left-9' : 'left-4'}
                peer-placeholder-shown:scale-100'
                peer-placeholder-shown:translate-y-0
                peer-focus:scale-75
                peer-focus:-translate-y-4
                ${errors[id] ? 'text-rose-500' : 'text-zinc-400'}
                `
                }

            >{label}</label>
        </div>
    )
}

export default Input;

Type 'OmitwithTag<InputProps, keyof PageProps, "default">' does not satisfy the constraint '{[x:string]: never;}'.

Property 'id' is incompatible with index signature. Type 'string' is not assignable to type 'never'.

Type error: Page "app/components/Input/page.tsx" has an invalid "default" export: Type "InputProps" is not valid.

Note: Working fine on localhost,giving error on build-time.


Solution

  • The file name app/components/Input/page.tsx is reserved in Next.js for routing purposes. For instance, page.{js,jsx,ts,tsx} within the app directory automatically generates a route. In this case, it would create a /components/Input route, which is likely unintended.

    Because it's a Next.js reserved file, Next.js expects you to only export some specific exports e.g. default component, runtime, revalidate, dynamic, etc...

    The default export must be a react component that accepts { params, searchParams } props. In your case it accepts InputProps which is not valid.

    I know you mean to make a reusable component not a route. so you must rename this file to non-reserved name. For example, name it Input.tsx or Input/index.tsx, not page, layout, route, default, template, not-found.

    It's better to move extra files (e.g. components) outside of the app directory, as it only responsible for routing.

    Instead of this structure:

    .
    └── app
        ├── components
        │   └── Input
        │       └── page.tsx
        ├── login
        │   └── page.tsx
        └── register
            └── page.tsx
    

    Make it like that:

    .
    ├── app
    │   ├── login
    │   │   └── page.tsx
    │   └── register
    │       └── page.tsx
    └── components
        └── Input
            └── page.tsx
    

    to avoid future conflicts like that