Skip to content

TypeScript Emits Invalid Index Signatures for Incompatible Object Properties #15

Description

@ravecat

Impact

Projects can receive generated TypeScript that passes the plugin's syntax validation but fails strict TypeScript compilation. This breaks the promise that successful generation returns importable contracts and blocks Feature #13 acceptance.

Observed behavior

The additional-properties compatibility check treats two object projections as equal when they contain the same property names, even if the property types differ. A fixed property of type { value: string } is therefore considered assignable to an index value of type { value: number }, and the plugin retains the incompatible typed index signature.

Expected behavior

A schema-valued additionalProperties type is retained only when every fixed property is assignable to it. Otherwise the index value widens to unknown, as required by the TypeScript interaction output specification.

Reproduction

  1. Define an object schema with required property fixed whose inline type is { value: string }.
  2. Set additionalProperties to an inline object type { value: number }.
  3. Run typescript() and compile the returned artifact with strict TypeScript settings.
  4. Observe that fixed is not assignable to the generated string index type.

Verification

  • The compatibility relation accounts for nested property types, requiredness, unions, arrays, tuples, references, and object index values used by the target AST.
  • Incompatible fixed properties widen the generated index value to unknown.
  • Compatible structured properties retain the projected typed index value.
  • A strict NodeNext regression fixture compiles the complete generated artifact tree.

Evidence

Generated shape:

export type InvalidTypedMap = {
  fixed: { value: string };
  [key: string]: { value: number };
};

Compiler diagnostic:

Property 'fixed' of type '{ value: string; }' is not assignable to 'string' index type '{ value: number; }'.

Linked artifacts

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: generationEntity discovery, naming, generation, and artifact planningbugSomething isn't workingoutput: typescriptTypeScript output and emitter behaviortestsTest coverage, fixtures, and test infrastructure

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions