Taming Numbers: How to Ensure Integer Properties in TypeScript
Type Annotation:
The most common approach is to use type annotations during class property declaration. Here, you simply specify the type of the property as
number
. In TypeScript,number
encompasses both integers and floating-point numbers. While this doesn't guarantee the property holds an integer exclusively, it does provide static type checking benefits. The compiler will warn you if you try to assign a non-numeric value to the property.class MyClass { age: number; // ... other properties and methods } const myInstance = new MyClass(); myInstance.age = 30; // Valid myInstance.age = 3.14; // Valid (but not an integer)
Custom Type Guard (Advanced):
For stricter type enforcement at runtime, you can create a custom type guard function. This function checks if a value is an integer and throws an error if not. You can then use this function within the class to validate assignments to the property.
function isInteger(value: number): value is number { return Number.isInteger(value); } class MyClass { private _age: number; set age(value: number) { if (!isInteger(value)) { throw new Error("Age must be an integer"); } this._age = value; } get age(): number { return this._age; } } const myInstance = new MyClass(); myInstance.age = 30; // Valid myInstance.age = 3.14; // Throws error
class Person {
age: number; // Property is declared as a number
constructor(age: number) {
this.age = age;
}
}
const person1 = new Person(30); // Valid assignment (integer)
const person2 = new Person(25.5); // Valid assignment (but not an integer)
function isInteger(value: number): value is number {
return Number.isInteger(value); // Check if value is an integer
}
class Product {
private _price: number;
set price(value: number) {
if (!isInteger(value)) {
throw new Error("Price must be an integer");
}
this._price = value;
}
get price(): number {
return this._price;
}
}
const product1 = new Product();
product1.price = 100; // Valid assignment (integer)
product1.price = 12.99; // Throws error (not an integer)
Interface with Validation (Similar to Custom Type Guard):
You can define an interface that mimics the behavior of the custom type guard function. This interface would have a single method to check if a value is an integer. Then, during class definition, you can extend this interface. This approach keeps the validation logic separate but offers a more structured way compared to a standalone function.
interface IntegerValidator { isInteger(value: number): boolean; } class Product implements IntegerValidator { private _price: number; isInteger(value: number): boolean { return Number.isInteger(value); } // ... other methods and properties }
Third-Party Libraries:
Remember:
- While these methods offer some level of type enforcement, they won't completely prevent accidental assignment of non-integer values. Runtime checks using
isInteger
or similar logic are still recommended for critical scenarios. - The first approach (type annotation) offers basic type checking during development, while the others provide more control but require additional setup. Choose the approach that best suits your project's needs and complexity.
typescript