fix(types): split converter/extensionService surfaces, type getActiveFormatting (SD-3240, SD-3245)#3434
Merged
caio-pizzol merged 3 commits intoMay 21, 2026
Conversation
…Formatting (SD-3240, SD-3245)
Add `EditorConverterSurface` and `EditorExtensionServiceSurface` as the
public no-`any` field types for `Editor.converter` and
`Editor.extensionService`. The runtime instances are still
SuperConverter / ExtensionService - a single `as unknown as <Surface>`
cast lives at the assignment boundary in Editor.ts. Internal callers
that need deeper member access narrow with a local structural type at
the call site, not via `any`.
`getActiveFormatting` gains a real signature: the editor parameter is a
narrow structural `{ state, storage.formatCommands.storedStyle }` shape;
the return is a discriminated union `{ name: 'copyFormat'; attrs: true }
| { name: string; attrs: Record<string, unknown> }`. The toolbar helpers
in `headless-toolbar/helpers/formatting.ts` narrow the union with a type
guard instead of reaching through `.attrs?.X` on a possibly-boolean
attrs (no casts).
Drains the final 18 supported-root allowlist entries (16 for SD-3240
converter/extensionService leaks across Editor / Extensions / SuperDoc
resolver call sites, 2 for SD-3245 getActiveFormatting param + return)
to 0. New `editor-surfaces-not-any.ts` fixture locks the contract with
`Equal<T, any>` checks so a regression breaks the typecheck matrix, not
just the allowlist JSON.
SD-3213 supported-root strict gate: PASS (0 entries).
…D-3240) Review caught three runtime/surface mismatches on EditorConverterSurface: - `getDocumentCreatedTimestamp()` returns ISO string `'2024-01-15T10:30:00Z'` or null (per `dcterms:created`), not `number | null`. The misclassification drove a misleading `String(timestamp)` coercion in `#trackDocumentOpen`; removed. - `getDocumentIdentifier()` is async and returns `Promise<string>` (the null fallback lives on `Editor.getDocumentIdentifier()` for the converter- missing case), not synchronous `string | null`. - `exportToDocx()` returns `Promise<string | Record<string, unknown>>` (XML string or intermediate JSON tree); Blob/Buffer wrapping happens upstream in `Editor.exportDocx()`. Added a one-line cast at the bridge site for the JSON branch to bridge to the (pre-existing, broader) implementation return type. Fixture coverage extended with exact-type assertions on each of the three methods so a future regression breaks the typecheck matrix, not the allowlist JSON. Also normalized em-dashes added in the prior commit to commas/colons/ periods per the writing-style rule (no em-dashes anywhere).
…240)
Adds the missing exact-type assertion on `editor.converter.exportToDocx()`
return (`Promise<string | Record<string, unknown>>`) alongside the
existing assertions for `getDocumentCreatedTimestamp`,
`getDocumentIdentifier`, and the converter / extensionService field
types. Locks the honest converter shape so a future drift back to
`any` (or to the original Blob | Buffer fiction) breaks the typecheck
matrix.
Note: the related `Editor.exportDocx({ exportJsonOnly: true })` overload
still publicly returns `Promise<string>` despite the runtime returning
a JSON tree object. That is a public Editor API correction (different
surface, different defect class) and is tracked separately as SD-3248.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Splits Editor.converter and Editor.extensionService into public no-any surface interfaces and types getActiveFormatting. The runtime instances stay SuperConverter / ExtensionService; the surface lives on the field types and a single as-unknown-as cast handles the assignment boundary. Toolbar helpers narrow the new getActiveFormatting discriminated union with a type guard instead of reaching through .attrs?.X.
Surfaced during review: Editor.exportDocx({ exportJsonOnly: true }) is publicly typed as Promise but actually returns a JSON tree at runtime. That is a separate public Editor API correction; tracked as SD-3248.
Verified: type-check → clean; pnpm test:editor → 13119 pass; deep-type-audit --pack --strict-supported-root → PASS; typecheck-matrix → 75/75