Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Declare every contract member on the interface, not bolted on at the use site
Widening an interface with an intersection type where it happens to be implemented means the interface no longer describes the contract, and other implementers or readers see an incomplete surface. If a member is a permanent part of the contract, declare it on the interface.
Bad example
| 1 | // ICacheModel.ts |
| 2 | export interface ICacheModel { cache: { get(...): void; set(...): void } } |
| 3 |
|
| 4 | // cacheModel.ts - the real surface, declared somewhere else |
| 5 | type Cache = ICacheModel["cache"] & { |
| 6 | wrap<T>(key: string, fn: () => Promise<T>, o: Options): Promise<T>; |
| 7 | del(key: string): void; |
| 8 | }; |
Explanation (EN)
Two of the four methods every caller uses are invisible from the interface file, so the declared contract is a subset of the real one.
Objašnjenje (HR)
Dvije od cetiri metode koje svaki pozivatelj koristi nevidljive su iz datoteke sucelja, pa je deklarirani ugovor podskup stvarnog.
Good example
| 1 | export interface ICacheModel { |
| 2 | cache: { |
| 3 | get<T>(key: string): Promise<T | null>; |
| 4 | set<T>(key: string, value: T, o: Options): void; |
| 5 | del(key: string): void; |
| 6 | wrap<T>(key: string, fn: () => Promise<T>, o: Options): Promise<T>; |
| 7 | }; |
| 8 | } |
Explanation (EN)
The interface is the whole contract, so a second implementation is checked against everything callers actually rely on.
Objašnjenje (HR)
Sucelje je cijeli ugovor, pa se druga implementacija provjerava prema svemu na sto se pozivatelji stvarno oslanjaju.
Notes (EN)
The tell is that the intersection lives next to the only implementation. If it were optional, someone would have written a second implementation without it.
Bilješke (HR)
Znak je to sto presjek stoji uz jedinu implementaciju. Da je neobavezan, netko bi vec napisao drugu implementaciju bez njega.
Exceptions / Tradeoffs (EN)
An intersection is fine for a genuinely local extension that other implementers are not expected to provide.
Iznimke / Tradeoffi (HR)
Presjek je u redu za stvarno lokalno prosirenje koje se od drugih implementacija ne ocekuje.