Revising the Answer
While some may disagree with this answer, it is important to acknowledge that as developers, we play a crucial role in structuring our data. The question posed here is very specific, asking how to model the "{number}px" type in TypeScript. The truth is, there is only one solution - it is not feasible. However, the misunderstanding lies in the fact that the questioner believes this type of format is the answer to their problem. In reality, the challenge is about representing a 2D point with x and y values along with a unit. This can easily be accomplished using a simple structure like [number, number, 'px'], indicating two numeric values and a static 'px' unit. This approach offers flexibility and type safety. Resorting to regular expressions or complex runtime validations through classes might seem like solutions but do not contribute during compilation.
Original Response:
Do you really need a class to represent a pair? Using a class for such a basic construct is like using a sledgehammer to crack a nut. What you truly require is a simple pair + unit representation, which can be achieved through a tuple [a, b, unit] or a record {a: a, b: b, unit: unit}. As pointed out by others, defining a type with a number followed by 'px' suffix is not possible, but there are several alternative modeling approaches. Here are a few suggestions:
1. Proposal One - Modeling with Additional Unit Information
// represented as a triple tuple
type Point = [number, number, string]
const point = [1, 2, 'px']
// represented as a key-value map
type Point = {x: number, y: number, unit: string}
const point = {x: 1, y: 2, unit: 'px'}
2. Model with Strict Unit Type.
If a strict unit like 'px' is certain, it can be defined in the type. I will only show examples using key-value map types to avoid repetition.
type Point = {x: number, y: number, unit: 'px'} // unit property must always be 'px'
const point = {x: 1, y: 2, unit: 'px'}
We can also create a constructor for points to eliminate manual entry of 'px':
const createPoint = (x: number, y: number): Point => ({x, y, unit: 'px'});
const point = createPoint(1, 2) // {x: 1, y: 2, unit: 'px'}
3. Modeling as a Pair of Strings but with Constructor
While leaving the type as a pair of strings, we can generate this using a number constructor.
type Point = {x: string, y: string}
const createPoint = (x: number, y: number): Point => ({x: x + 'px', y: y + 'px'});
const point = createPoint(1, 2) // {x: '1px', y: '2px'}
4. Modeling as an Object with Special Get Functions
type Point = {values: () => {x: number, y: number}, pixels: () => {x: string, y: string}}
// utilizing closure to store arguments of createPoint function
const createPoint = (x: number, y: number): Point => ({
values: () => ({x, y}),
pixels: () => ({x: x + 'px', y: y + 'px'})
})
const point = createPoint(1, 2);
point.values() // {x: 1, y: 2}
point.pixels() // {x: '1px', y: '2px'}