A company directory may receive a rating value, a review count and a source URL. Saving only 4.8 discards the information a reader needs to interpret it. What scale was used? Where did the value come from? When was it checked?
This is a small TypeScript design exercise for directory builders. It is not a description of a deployed Raiting.kz integration, and it does not assume permission to collect data from any external platform. Use a source only when its terms and your access permit it.
Keep the observation together
type RatingObservation = Readonly<{ companyId: string; sourceUrl: string; sourceName: string; value: number; scaleMax: number; reviewCount: number | null; observedAt: string; }>; function isUsableRating(r: RatingObservation): boolean { return Number.isFinite(r.value) && Number.isFinite(r.scaleMax) && r.scaleMax > 0 && r.value >= 0 && r.value <= r.scaleMax && (r.reviewCount === null || (Number.isSafeInteger(r.reviewCount) && r.reviewCount >= 0)) && Number.isFinite(Date.parse(r.observedAt)); } The function checks basic consistency. It does not prove that the source is genuine, that a URL belongs to the right company or that reviews are reliable. Those are separate checks. For production, parse incoming data from unknown with a runtime schema before calling code that expects this type.
reviewCount: null means the count was not available. It must not become zero: zero is a factual claim that no reviews were counted. The same distinction matters for missing ratings. Avoid using zero as the default score for a company whose rating was never checked.
An observation time is not a review date
observedAt records when your system or editor checked the source. The underlying reviews may be older. If the source exposes a last-updated date, store it in a separate field rather than overwriting the observation time.
Use an explicit timestamp with an offset or UTC. In the display layer, format it for the reader's locale. A later observation should create a new record if historical comparison matters; overwriting the earlier value makes it impossible to explain a change.
Display a qualified value
A useful card might say: "4.8 out of 5, 127 reviews, source: Example Directory, checked 3 November 2026." These are fictional values for the example. The source name should link to the original public card.
If the count is unknown, say so or omit the count. If the observation is old, show the date instead of presenting it as live. Define a review policy for stale records; there is no single freshness interval that suits every service.
Do not silently blend sources
Two platforms can use different scales, moderation rules and review populations. Converting both values to percentages does not remove those differences. Keep separate observations visible unless you have an explicit, defensible aggregation method. Document that method before displaying a combined value.
An editorial ranking is another object altogether. It needs its own category, geography, comparison date and method version. A user rating should not accidentally become the editorial score because both happen to fit into a numeric database column.
Make corrections traceable
If a company points out that the source URL belongs to a different branch, retain the correction reason and update the mapping. A valid-looking number attached to the wrong company is still wrong. Keep an internal audit trail without publishing personal correspondence.
This separation supports a simple interface: a number, its source, its date and any limitation that changes how a reader should use it. It also makes later debugging more concrete: is the problem in collection, identity matching, freshness or presentation?
Context
These notes are prepared for Raiting.kz, a company discovery and comparison project in Kazakhstan. Its published methodology provides context for editorial comparisons. The code above remains an illustrative implementation pattern, not a claim about current platform functionality.
Text generated with AI for Raiting.kz. Cover illustration generated with AI for Raiting.kz.
