[Bug]: State.SQLite.table(S.transform(..)) typing is wrong
#680 opened on Sep 23, 2025
Repository metrics
- Stars
- (3,599 stars)
- PR merge metrics
- (PR metrics pending)
Description
Bug Description
My stuff works after LS-197 thanks! The following is not blocking but just to document known issues that require me to do manual workarounds.
-
S.optionalon fields (of encoded side) gets represented asfield: T | undefinedinstead offield?: T | undefined. This should correctly forward the?part. -
selectreturns the encoded version of the encoded but claims it returns the decoded version of encoded. I.e. if the "from" side of the transform has adate: S.DateFromStringthen the actual value returned byselectisstringwhile typescript infers aDate. This should represent the reality - the types should infer encoded version of encoded.In the long run though, it should return the decoded version of the decoded side of the transfer, I saw your TODO. If you're thinking to make it at least return Date in the short term, don't because my workaround below would break (calling transform from one end to the other, so if you decode the "from" side then my end to end decode won't work).
My workaround for the above is to create a separate transform which has both sides as deeply partial because I can specify dynamic fields in select and I assume schema would fail with missing fields.
S.partialis shallow, so I have to type all nested objects manually and useS.extend(S.partial(MyStuff.omit('nestedObj')), S.Struct({nestedObj: S.optional(S.partial(MyStuffNestedObj)){))). Then I'd calldecodeSyncfrom it onto the result ofselectand that works. -
field: S.Literal('a', 'b')when used on the same field in both sides ofS.transform()seems to only expect the first literal in the list, so if the value is'b'then it'll sayexpected 'a', actual 'b'. This happened when I published a create event, then successfully encoded it (as per the bug 2 above) viaS.encodeSync(MyTransform)(eventWithStructureMatchingDecoded), then passed the result into theinsertand then I saw the above error which came fromMyTransform. After I made the field intoS.Stringon the encoded side, it worked.Update: this is actually reproducing on
S.Structtables too, so it's not just aboutS.transform. For non-transform, it worked after I changedS.Literal(...Object.values(MyActualEnum))to this:const MyEnum = S.transform(S.String, S.Literal(...Object.values(MyActualEnum)), { strict: true, decode: input => input as MyActualEnum, encode: output => output })
LiveStore Version
0.4.0-dev.8
Which package(s) are affected?
@livestore/common