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 MyInterfaceTypeScript requires structural overlap for direct casts. A typed interface and Record<string, unknown> (index signature) don't share enough structure.