DEV Community

Generatecode
Generatecode

Posted on • Originally published at generatecode.dev

How to Validate a Number with Specific Decimal Places in TypeScript?

When working with numbers in TypeScript, particularly for financial applications, it's crucial to ensure that the values conform to specific formats and constraints. In your case, you want to validate a number that can have up to 18 digits before the decimal point and exactly 2 digits after. This demand for precision and structure can be effectively handled by the popular class-validator library. This article will explain how you can implement this validation using TypeScript’s class-validator.

Understanding Class Validator

class-validator is a powerful library that allows you to apply constraints and validations on class properties. It’s beneficial in various scenarios, especially for validating user inputs in your applications. Using decorators, you can easily express validation rules, enabling your code to be more readable and maintainable.

The Challenge of Number Validation

The challenge arises when you need to validate a number that adheres to strict formatting rules. While the @IsNumber() decorator allows you to validate decimal places, to enforce specific limitations on the range of numbers, additional logic is needed.

In your scenario, the requirements are:

  • A maximum of 18 digits before the decimal point.
  • Exactly 2 digits after the decimal point.

Given these requirements, employing a combination of the @IsNumber(), @Min(), and @Max() decorators will not be sufficient. We’ll also need to create a custom validation decorator to implement the digit restrictions before the decimal point.

Step-by-Step Solution

Let's create a TypeScript class that incorporates the validation logic using class-validator.

Step 1: Setup Your TypeScript Class

You will define your class and include the relevant decorators from class-validator. Here is how you can do it:

import { IsNotEmpty, IsNumber, Min, Max, Validate } from 'class-validator';
import { Expose } from 'class-transformer';

// Custom Decorator for 18 digits before the decimal
function IsValidAmount() {
    return Validate(
        (value: number) => {
            const numberString = value.toString();
            const parts = numberString.split('.');
            // Check if the integer part has more than 18 digits
            if (parts[0].length > 18) {
                return false;
            }
            // Check if the fractional part has exactly 2 digits
            if (parts.length === 2 && parts[1].length === 2) {
                return true;
            }
            return false;
        },
        { message: 'Amount must have up to 18 digits before the decimal and 2 after.' }
    );
}

export class PaymentBasicData {
    /**
     * Transaction amount.
     */
    @Expose()
    @IsNotEmpty()
    @IsNumber({ maxDecimalPlaces: 2 })  // Confirms max decimal places
    @IsValidAmount()                    // Custom validation
    @Min(0.01)
    @Max(999999999999999999.99)
    public amount: number;
}

Step 2: Explanation of the Code

  1. Imports: You import required decorators and utilities from the class-validator and class-transformer packages.
  2. Custom Decorator: The IsValidAmount function is a custom validator that checks whether the provided number meets the specified criteria. It converts the number to a string, splits it into integer and fractional parts, and performs checks accordingly.
  3. Class Definition: Within the PaymentBasicData class, your defined rules are applied to the amount property. This ensures that it adheres to the validation criteria whenever it is instantiated or validated.

Step 3: Validation Example

To see how this works in practice, you can instantiate your class and validate it:

import { validate } from 'class-validator';

const paymentData = new PaymentBasicData();
paymentData.amount = 123456789012345678.12;

validate(paymentData).then(errors => {
    if (errors.length > 0) {
        console.log('Validation failed. Errors: ', errors);
    } else {
        console.log('Validation succeed.');
    }
});

In this example, if amount has more than 18 digits before the decimal or doesn't have exactly 2 digits after the decimal, validation will fail, and the relevant error messages will be displayed.

Frequently Asked Questions

What if I need a different number of digits?

To change the required number of digits, simply modify the logic inside the IsValidAmount function accordingly.

Can I run multiple validations on the same property?

Yes, you can apply multiple decorators to the same property to cover various validation needs.

How do I use this in a real application?

In a real application, you can invoke validations when user inputs are received, ensuring the data is valid before processing.

Conclusion

In summary, validating numbers with specific formats is essential for maintaining data integrity, especially in financial applications. By combining built-in validators with custom ones, you can ensure that your application enforces stringent validation rules. In the example provided, we explored how to implement a validator ensuring that the number matches the criteria of having up to 18 digits before the decimal point and exactly 2 digits after. This method can greatly enhance the robustness of data handling in your TypeScript applications.

Top comments (0)