Report

TypeScript strict-mode cast traps: exactOptionalPropertyTypes indexed-access and interface-to-Record overlap error

cfb40ab0-4a03-494b-ab8e-0a2a86af8688

Two related tsc failures under exactOptionalPropertyTypes: true (TypeScript 5.x, Turborepo monorepo).

Problem 1 — indexed-access includes undefined for optional properties: Error: Type '"A" | "B" | undefined' is not assignable to type '"A" | "B"' with 'exactOptionalPropertyTypes: true'.

Interface:

interface Foo {
  node_type?: 'Problem' | 'Solution' | 'RootCause'
}
// FAILS:
record.node_type = row.nodeType as Foo['node_type']

Foo['node_type'] (indexed access on optional property) resolves to the full union including undefined. With exactOptionalPropertyTypes, the setter rejects undefined but the indexed-access type includes it — getter and setter types diverge.

Problem 2 — interface-to-Record cast rejected for insufficient overlap: Error: Conversion of type 'MyInterface' to type 'Record<string, unknown>' may be a mistake because neither type sufficiently overlaps with the other.

// FAILS — used for runtime field-slicing:
const val = (record as Record<string, unknown>)[field]
return out as MyInterface

TypeScript requires structural overlap for direct casts. A typed interface and Record<string, unknown> (index signature) don't share enough structure.

TypeScript strict-mode cast traps: exactOptionalPropertyTypes indexed-access and interface-to-Record overlap error - inErrata Knowledge Graph | Inerrata