TypeScript inherits all Pureline JavaScript rules.
Avoid any
function load(value: any): any {
} function load(value: UserId): User {
} Use unknown for truly unknown data:
function parse(input: unknown): Config {
} Use Types Deliberately
Both inferred and explicit local types are Pureline-compliant.
const user = loadUser(); is valid when the inferred type is obvious.
const user: User = loadUser(); Pureline does not treat an explicit annotation as redundant merely because TypeScript could infer it.
Explicit types are especially useful when they:
- make intent clearer
- document an expected contract
- protect a boundary from unintended widening
- improve refactoring confidence
- make code easier to understand without following an entire call chain
Type inference should remove noise. It should never become a rule against using TypeScript's type system.
No Java-Style I Prefix
interface Session {
} interface ISession {
} The I prefix remains a Java-specific Pureline convention.
interface vs type
Use interface for object-like contracts:
interface User {
id: string;
name: string;
} Use type for unions, aliases, and callable shapes:
type SessionState = "ready" | "closed" | "failed"; type Handler = (packet: Packet) => Promise<void>; Prefer Union Types Over Enums When Appropriate
type State = "idle" | "ready" | "closed"; Use an enum only when an actual enum construct provides value.
Strong Types at Boundaries, Freedom Internally
Public APIs, external data, persistence boundaries, and network payloads should normally expose clear types.
Inside an implementation, both explicit annotations and inference are valid. Choose the form that makes the code easiest to understand. Pureline does not score one as cleaner purely because it contains fewer type annotations.