Release v22.10.0
Added
--emit-interfacesrenders types as plain TypeScript interfaces rather than classes carrying@fielddecorators, with no@cratis/fundamentalsimport for the decorators. A model that is only ever built and read needs neither, and a package that deliberately carries no dependencies cannot take one on. Documentation, base types and nullability are unchanged, so the output differs from the class form only in the ways the mode is for. (#2635)
Fixed
- A read-only dictionary is now recognized as a dictionary.
IsDictionaryonly looked forIDictionary<,>, andIReadOnlyDictionary<,>is its sibling rather than its derivative — so a model exposing its dictionaries read-only, the natural shape for an immutable record, was not seen as holding dictionaries at all.IReadOnlyDictionary<string, IReadOnlyList<T>>now generates asRecord<string, T[]>instead of aKeyValuePair[]referencing a type that was never imported. (#2634) - Library mode no longer aborts on a model with two read-only dictionaries. Those unrecognized dictionaries put two closed instantiations of
KeyValuePair<,>in one output file, and the duplicate-path guard stopped the entire run. With them recognized,CollectTypesInvolvedtakes only the value type as it always did for the mutable shape, and noKeyValuePairis emitted. (#2634) - Library mode no longer aborts on an open generic either. It collected open definitions such as
CompilationResult<T>, and walking one reached its own type parameter — which has no full name, so it produced a nameless descriptor landing on the definition's own path. An open definition has no concrete shape to emit and a generic parameter is not a type, so both are skipped. (#2634)
Verified against two independent model assemblies. The second one is why the third fix exists: after the dictionary fix I claimed the collision could no longer arise, which was true only of dictionaries — checking Cratis.Screenplay surfaced a second, unrelated cause.
| assembly | before | after |
|---|---|---|
Cratis.Scene.Model |
aborts on the KeyValuePair collision |
75 files, no exclusions needed |
Cratis.Screenplay |
aborts on the CompilationResult<T> collision |
216 files, 193 types |
With --emit-interfaces, Scene emits zero @cratis/fundamentals imports. Screenplay emits one — TimeOnly, a value type Fundamentals provides rather than a decorator, which no emission mode can or should remove.
The Interface template already existed but was unused and incomplete — it gained documentation, extends and optional properties here rather than being written from scratch.
Four generated files under TestApps also change, and not because of anything in this PR: their committed output predates the XML-doc unescaping fix, so ` becomes a backtick when they are regenerated. Left in rather than reverted, so main stops carrying stale generated output.
Verified: 51 projects build in Release with 0 errors and 0 warnings, and 1225 ProxyGenerator specs pass — including 17 new ones covering all three changes.
🤖 Generated with Claude Code