Accept free-form Any property types in @Record - #58
Merged
Merged
Conversation
A `@Record` property typed `[String: Any]?` (or any type holding `Any`) failed the conformance assertion, since `Any` can't be `JavaScriptDecodable & JavaScriptEncodable`. Such a property now converts on the JS-value paths through the `JavaScriptValue` free-form methods from `expo-modules-jsi`: `decodeAny`/`decodeAnyArray`/`decodeAnyDictionary` and the matching `encodeAny…` for `Any`, `[Any]` and `[String: Any]` (optional or not), and the generic `decodeAny(_:as:in:)`/`encodeAny(_:in:)` for other shapes built from `Any`, arrays, `String`-keyed dictionaries and optionals. Any other type holding `Any` (`[Int: Any]`, `Box<Any>`) is a compile-time error, since it could never convert. Such a property only asserts `AnyArgument`, and a bare `Any` asserts nothing and passes through the dictionary paths unchanged. `Swift.Any` is recognized as `Any`. The optional unwrapping is shared with `@ViewProps` through `optionalWrappedType`.
tsapeta
force-pushed
the
tsapeta/record-free-form-any-fields
branch
from
September 25, 2026 20:27
7441316 to
1042335
Compare
tsapeta
marked this pull request as ready for review
September 25, 2026 20:29
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.
Why
A
@Recordproperty typed[String: Any]?doesn't compile today: every property must beAnyArgument & JavaScriptDecodable & JavaScriptEncodable, andAnycan't conform to the codable protocols. There's no conformance-level fix (a secondDictionaryconformance or extendingAnyare both rejected by the compiler), so it has to be handled in the macro. This unblocks theattributesargument onObserve.reportErrorinexpo-observe(ENG-25264).How
A property whose type mentions
Anynow converts on the JS-value paths through theJavaScriptValuefree-form methods added in expo/expo#50660, not dynamic types:from(object:)toObjectAny,[Any],[String: Any](optional or not)decodeAny/decodeAnyArray/decodeAnyDictionaryencodeAny/encodeAnyArray/encodeAnyDictionaryAny, arrays,String-keyed dictionaries and optionals ([String: [Any]]?, …)decodeAny(_:as:in:)encodeAny(_:in:)Any other type holding
Any, like[Int: Any]orBox<Any>, is a compile-time error pointing toJavaScriptValue, since those conversions could never produce or accept it.Such a property only asserts
AnyArgument, which the dictionary paths still need, since they keep casting throughgetDynamicType()like every other property. A bareAnyhas no dynamic type, so it asserts nothing and the dictionary paths pass it through unchanged.The generated code calls methods that only exist once expo/expo#50660 lands, so a release with this change needs a core that includes it.
Test Plan
New
RecordMacroTestsexpansion tests cover the dedicated shapes, the generic path, bareAny,Swift.Any, and the diagnostic for shapes that can't convert. The fullswift testrun passes (286 tests).