skip to Main Content

I have a STEPS_CONFIG object that defines various steps, each with a set of properties including defaultValues. However, when I try to access defaultValues from the currentStep object, TypeScript throws an error indicating that the property does not exist on the type.

Here’s a version of the relevant code:

export const STEPS = {
  init: 'init',
  profile_picture: 'profile_picture',
  driving_license_front: 'driving_license_front',
  driving_license_back: 'driving_license_back',
  vehicle_card_front: 'vehicle_card_front',
  vehicle_card_back: 'vehicle_card_back',
  vehicle_insurance: 'vehicle_insurance',
  verification_photo: 'verification_photo',
  applicant_contract: 'applicant_contract',
} as const;

export const STEPS_CONFIG = () => ({
  [STEPS.init]: {
    title: `${t('enterBasicInformation')}`,
    renderForm: <Init />,
    // TODO: Remove unused properties from the init step and fix possible errors
    properties: {
      boxTitle: 'Box Title',
      rulesList: ['rule1', 'rule2', 'rule3'],
      image: 'aedfsdafsdf',
      selfieMode: false,
      enabled: false,
    },
    onSubmit: async (data: any) => {
      const formattedData = {
        vehicle_type: 'cab' as const,
        referral_code: toEnNumbers(data.referralCode),
        national_code: toEnNumbers(data.nationalCode)!,
        activity_location: data.activityLocation.id as number,
        father_name: data.fatherName as string,
      };
      const response = await init(formattedData);
      if (response.ok) {
        useWizardStore
          .getState()
          .addRemainingSteps(response.body.remaining_steps);
      }
      return response;
    },
    defaultValues: {
      vehicleType: 'سواری',
      haveReferralCode: false,
      activityLocation: null,
      fatherName: '',
      nationalCode: '',
    },
  },
  [STEPS.profile_picture]: {
    title: `${t('uploadProfilePicture')}`,
    description: `${t('takeSelfieRule')}`,
    properties: {
      boxTitle: `${t('userSelfie')}`,
      rulesList: [
        `${t('fullViewImageRule')}`,
        `${t('profilePictureExtraRules')}`,
      ],
      image: getFileURL('images/rules/profile-picture.svg'),
      correctionImage: useWizardStore.getState().remainingSteps.profile_picture,
      selfieMode: true,
      enabled: true,
    },
    onSubmit: async (data: any) => {
      const formattedData = {
        kind: STEPS.profile_picture,
        image: data.image,
      };
      const response = await uploadDocument(formattedData);
      return response;
    },
  },
  [STEPS.driving_license_front]: {
    title: `${t('uploadDrivingLicenseFront')}`,
    description: `${t('takeDrivingLicnseRuleFront')}`,
    renderForm: <DrivingLicenseFront />,
    properties: {
      boxTitle: `${t('drivingLicenseFrontImage')}`,
      rulesList: [`${t('originalDocumentRules')}`, `${t('overEighteenRules')}`],
      image: getFileURL('images/rules/driving-license-front.svg'),
      correctionImage:
        useWizardStore.getState().remainingSteps.driving_license_front,
      selfieMode: false,
      enabled: true,
    },
    onSubmit: async (data: any) => {
      const formattedData = {
        kind: STEPS.driving_license_front,
        image: data.image,
        first_name: data.firstName,
        last_name: data.lastName,
        birth_date: toEnNumbers(data.birthDate)!,
        gender: data.gender.value,
        license_issuance_date: toEnNumbers(data.licenseIssuanceDate)!,
        license_valid_for: data.drivingLicenseValidityPeriod.value,
        license_type: data.drivingLicenseType.value,
        license_number: toEnNumbers(data.drivinglicenseNumber)!,
      };
      const response = await uploadDocument(formattedData);
      return response;
    },
  },
  [STEPS.driving_license_back]: {
    title: `${t('uploadDrivingLicenseBack')}`,
    description: `${t('takeDrivingLicnseRuleBack')}`,
    properties: {
      boxTitle: `${t('drivingLicenseBackImage')}`,
      rulesList: [
        `${t('originalDocumentRules')}`,
        `${t('readableDrivingLicenseBack')}`,
      ],
      image: getFileURL('images/rules/driving-license-back.svg'),
      correctionImage:
        useWizardStore.getState().remainingSteps.driving_license_back,
      selfieMode: false,
      enabled: true,
    },
    onSubmit: async (data: any) => {
      const formattedData = {
        kind: STEPS.driving_license_back,
        image: data.image,
      };
      const response = await uploadDocument(formattedData);
      return response;
    },
  },
  [STEPS.vehicle_card_front]: {
    title: `${t('uploadVehicleCardFront')}`,
    description: `${t('takeVehicleCardFrontRule')}`,
    renderForm: <VehicleCardFront />,
    properties: {
      boxTitle: `${t('vehicleCardFrontImage')}`,
      rulesList: [
        `${t('originalDocumentRules')}`,
        `${t('clearDocumentRules')}`,
        `${t('exactCarRules')}`,
      ],
      image: getFileURL('images/rules/vehicle-card-front.svg'),
      correctionImage:
        useWizardStore.getState().remainingSteps.vehicle_card_front,
      selfieMode: false,
      enabled: true,
    },
    onSubmit: async (data: any) => {
      const formattedData = {
        kind: STEPS.vehicle_card_front,
        image: data.image,
        ...(data.plate.part_a && { plate_part_a: data.plate.part_a }),
        ...(data.plate.part_b && { plate_part_b: data.plate.part_b }),
        ...(data.plate.iran_id && { plate_iran_id: data.plate.iran_id }),
        ...(data.plate.character && { plate_character: data.plate.character }),
        plate_type: data.plate.type,
        vin: data.vin,
      };
      const response = await uploadDocument(formattedData);
      return response;
    },
    defaultValues: {
      plate: {
        type: 1,
        part_a: null,
        part_b: null,
        character: null,
        iran_id: null,
      },
      vin: '',
    },
  },
  [STEPS.vehicle_card_back]: {
    title: `${t('uploadVehicleCardBack')}`,
    description: `${t('takeVehicleCardBackRule')}`,
    renderForm: <VehicleCardBack />,
    properties: {
      boxTitle: `${t('vehicleCardBackImage')}`,
      rulesList: [
        `${t('originalDocumentRules')}`,
        `${t('clearDocumentRules')}`,
        `${t('exactCarRules')}`,
      ],
      image: getFileURL('images/rules/vehicle-card-back.svg'),
      correctionImage:
        useWizardStore.getState().remainingSteps.vehicle_card_back,
      selfieMode: false,
      enabled: true,
    },
    onSubmit: async (data: any) => {
      const formattedData = {
        kind: STEPS.vehicle_card_back,
        image: data.image,
        vehicle_model_id: data.vehicleModel.id,
        vehicle_color_id: data.vehicleColor.id,
        fuel_type: data.fuelType.value,
        vehicle_production_year: toEnNumbers(data.productionYear)!,
      };
      const response = await uploadDocument(formattedData);
      return response;
    },
    defaultValues: {
      vehicleColor: null,
      vehicleModel: null,
      productionYear: '',
    },
  },
  [STEPS.vehicle_insurance]: {
    title: `${t('uploadVehicleInsurance')}`,
    description: `${t('takeVehicleInsuranceRule')}`,
    renderForm: <VehicleInsurance />,
    properties: {
      boxTitle: `${t('vehicleInsuranceImage')}`,
      rulesList: [
        `${t('originalDocumentRules')}`,
        `${t('fillInsuranceCodeRules')}`,
        `${t('insuranceCodeDigitsRules')}`,
        `${t('onlyInsuranceCodeRules')}`,
        `${t('theNewestVehicleInsuranceRules')}`,
      ],
      image: getFileURL('images/rules/vehicle-insurance.svg'),
      correctionImage:
        useWizardStore.getState().remainingSteps.vehicle_insurance,
      selfieMode: false,
      enabled: true,
    },
    onSubmit: async (data: any) => {
      const formattedData = {
        kind: STEPS.vehicle_insurance,
        image: data.image,
        insurance_id: toEnNumbers(data.insuranceNumber)!,
        insurer_national_code: toEnNumbers(data.insurerNationalCode)!,
        insurance_expiration_date: toEnNumbers(data.insuranceExpirationDate)!,
      };
      const response = await uploadDocument(formattedData);
      return response;
    },
    defaultValues: {
      hasInsuranceNumber: false,
    },
  },
  [STEPS.verification_photo]: {
    title: `${t('verificationPhoto')}`,
    description: `${t('takeVerificationPhotoRule')}`,
    properties: {
      boxTitle: `${t('verificationImage')}`,
      rulesList: [`${t('keepLicenseRules')}`],
      image: getFileURL('images/rules/verification-photo.svg'),
      correctionImage:
        useWizardStore.getState().remainingSteps.verification_photo,
      selfieMode: true,
      enabled: true,
    },
    onSubmit: async (data: any) => {
      const formattedData = {
        kind: STEPS.verification_photo,
        image: data.image,
      };
      const response = await uploadDocument(formattedData);
      return response;
    },
  },
  [STEPS.applicant_contract]: {
    title: `${t('takeSignatureTitle')}`,
    renderForm: <ApplicantContract />,
    properties: {
      boxTitle: `${t('takeSignatureTitle')}`,
      rulesList: [
        `${t('uploadContractRules')}`,
        `${t('confirmContractRules')}`,
      ],
      image: getFileURL('images/rules/applicant-signature.svg'),
      correctionImage:
        useWizardStore.getState().remainingSteps.applicant_contract,
      selfieMode: false,
      enabled: true,
    },
    onSubmit: async (data: any) => {
      const formattedData = {
        kind: STEPS.applicant_contract,
        image: data.image,
        training_place_id: data.trainingPlace.id,
      };
      const response = await uploadDocument(formattedData);
      return response;
    },
  },
});


 const currentStep =
    STEPS_CONFIG()[stepLabels[activeStep] as keyof typeof STEPS];

const methods = useForm({
    mode: 'all',
    defaultValues: currentStep.defaultValues,
  });

and in this line

defaultValues: currentStep.defaultValues,

I got this error

Property 'defaultValues' does not exist on type '{ title: string; description: string; properties: { boxTitle: string; rulesList: string[]; image: string; correctionImage: { image_url: string; message: string; } | undefined; selfieMode: boolean; enabled: boolean; }; onSubmit: (data: any) => Promise<any>; }'.

2

Answers


  1. Maybe you can try:
    Define an interface for the structure of each step in STEPS_CONFIG. Ensure this interface includes the defaultValues property.

    Than something like this:

    interface StepConfig {
      title: string;
      description?: string;
      renderForm?: JSX.Element;
      properties: {
        boxTitle: string;
        rulesList: string[];
        image: string;
        correctionImage?: any;
        selfieMode: boolean;
        enabled: boolean;
      };
      onSubmit: (data: any) => Promise<any>;
      defaultValues?: any;
    }
    
    export const STEPS_CONFIG = (): Record<keyof typeof STEPS, StepConfig> => ({
      [STEPS.init]: {
        defaultValues: {
          // default values for the init step
        },
      },
      [STEPS.profile_picture]: {
        // no defaultValues if not needed for this step
      },
    });
    
    const currentStep: StepConfig = STEPS_CONFIG()[stepLabels[activeStep] as keyof typeof STEPS];
    
    const methods = useForm({
        mode: 'all',
        defaultValues: currentStep.defaultValues || {},
    });
    
    
    Login or Signup to reply.
  2. You do not have a defaultValues property on every possible value, thus Typescript (correctly) does not infer it in the resulting type. I would advise against using such a huge type structure without an explicit type or interface definition.

    Define an interface for the STEPS_CONFIG values explicitly.
    That also has the advantage that you have type validation for your step definitions.

    interface StepConfig { 
      title: string; 
      description: string; 
      properties: { boxTitle: string; rulesList: string[]; image: string; correctionImage: { image_url: string; message: string; } | undefined; selfieMode: boolean; enabled: boolean; }; 
      onSubmit: (data: any) => Promise<any>; 
      defaultValues?: any; // Whatever?
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search