Join our Newsletter — 33% off our NHI Course
Home FAQ Cyber Security What breaks when TypeScript type information is lost…
Cyber Security

What breaks when TypeScript type information is lost at runtime in a union-based design?

← Back to all FAQ
By NHI Mgmt Group Editorial Team Updated September 10, 2026 Domain: Cyber Security

The compiler can narrow types during development, but the running code no longer knows which concrete type it received. That means logic inside the logger cannot safely infer whether a document is a user, plugin, or playbook unless you pass that context explicitly. Without a runtime discriminator, the function cannot apply type-specific rules reliably.

Why Runtime Type Erasure Changes the Logging Problem

Once TypeScript compiles to JavaScript, union types exist only for developer tooling and build-time checks, not for the running program. That matters when a logger or policy function needs to choose different handling for a user, plugin, or playbook, because the runtime sees plain objects, not the original type intent. If the code relies on compile-time narrowing alone, it can silently apply the wrong rule, skip a required check, or produce misleading telemetry. For exact control expectations around runtime validation and object handling, NIST SP 800-53 Rev 5 Security and Privacy Controls can help teams think about enforcement points rather than assumptions made during development. In practice, teams usually discover this gap only after a generic handler has already processed a shape it could not truly distinguish.

How Union-Based Designs Fail Without a Runtime Discriminator

A union-based design works well when the compiler can help author the code, but the compiled function still needs an explicit signal to know which branch it is executing. If the logger accepts several document shapes, it must be able to distinguish them from data that exists at runtime, such as a kind field, a tagged enum, or a validated schema result. Without that, any branch-specific behaviour becomes guesswork.

This is not just a typing concern. It affects validation, audit formatting, redaction, enrichment, and conditional routing. A logger may need to suppress a secret for one document class, enrich another with user context, or forward a third to a different sink. If the code only trusts the union declared in TypeScript, those choices become unsafe because the runtime cannot inspect erased type metadata.

  • Use a discriminator that is present in the payload itself, not only in the type declaration.
  • Validate the input before branch selection if the source is external or loosely typed.
  • Keep logging rules tied to explicit fields or schemas, not inferred object shape alone.
  • Treat compile-time narrowing as developer assistance, not as a runtime assurance.

The guidance breaks down when the design assumes the compiler will enforce distinctions that the production process never preserves.

Edge Cases: When the Union Looks Safe but Still Isn’t

Tighter type safety often increases design overhead, requiring teams to balance cleaner code against the cost of carrying runtime markers through every object shape. That tradeoff becomes visible when one variant is structurally similar to another, because structural typing can make two different concepts appear interchangeable until a branch needs a unique rule.

There is also a consensus gap in teams that mix logging, validation, and transport concerns. Some developers assume a discriminated union is enough if the TypeScript compiler accepts it; others insist that every externally supplied object must be revalidated at the boundary. The practical answer is that the second view is safer whenever the data crosses process, package, or trust boundaries.

Another edge case appears when the same logger is reused across service layers. A shape that is obvious inside one module may become ambiguous after serialization, deserialization, or partial projection. If the distinguishing field is dropped anywhere in that path, the branch logic loses its basis. In those cases, the design is not broken by TypeScript itself, but by the absence of a runtime source of truth for the decision.

Risk and Threat Considerations

The material risk is incorrect handling of data that looks typed during development but is indistinguishable at runtime. In logging, redaction, routing, and policy enforcement, that can create confidentiality, integrity, and auditability failures because the wrong branch may process the wrong object class.

Failure mechanism: The program relies on erased compile-time unions instead of a runtime discriminator or validated schema, so branch selection is based on assumption rather than observable evidence. When similar object shapes are accepted, the code can misclassify an input and apply the wrong rule set.

Impact: Sensitive fields may be logged, required enrichment may be skipped, telemetry may be misleading, and downstream consumers may make decisions from an incorrect record type.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

MITRE ATT&CK address the attack and risk surface, while NIST CSF 2.0 and CIS Controls v8 set the governance and control requirements practitioners need to meet.

FrameworkControl / ReferenceRelevance
NIST CSF 2.0PR.DS — Data SecurityRuntime misclassification can expose or mishandle protected data.
PR.AC — Identity Management, Authentication and Access ControlBranch logic depends on trustworthy object classification before privilege-sensitive actions.
Recommendation — Apply PR.DS to ensure sensitive fields are handled according to explicit runtime classification. Apply PR.AC to require explicit trust signals before policy decisions act on a record.
CIS Controls v83 — Data ProtectionIncorrect runtime handling can cause logging or redaction failures for sensitive information.
8 — Audit Log ManagementThe topic directly concerns reliable log generation and type-specific audit handling.
Recommendation — Use CIS Control 3 to validate data handling rules before records reach logging pipelines. Use CIS Control 8 to ensure log entries are generated from validated runtime context.
MITRE ATT&CKT1078 — Valid AccountsIf a misclassified object grants inappropriate processing, trust is being abused through accepted input.
Recommendation — Map trust abuse in input handling to T1078-style validation gaps and inspect accepted-object paths.

Practitioner Guidance

What to verify: Confirm that every union member has a runtime-visible discriminator or an equivalent validation result before any type-specific logging or policy logic runs.

Common mistake: Teams often trust TypeScript narrowing inside the implementation and forget that production JavaScript cannot recover the original union member once the type has been erased.

Decision rule: If the logger’s behaviour changes by document class, the classification must be carried in the data or reconstructed from validated input; if it cannot be, treat the branch as unsafe and keep the handling generic.

Practitioner takeaway: The safest union design is the one that preserves its decision signal at runtime, because compile-time correctness does not protect a production function that no longer knows what it received.

Deepen Your Knowledge

Sign up to our weekly newsletter — get 33% off our NHI Foundation Level Course

    NHIMG Editorial Note
    Reviewed and updated by the NHIMG editorial team on September 10, 2026.
    NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org