-
Notifications
You must be signed in to change notification settings - Fork 139
Truthy #895
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Changed `getAll` return type to use `Truthy<T>` instead of `NonNullable<T>` - Added `Truthy<T>` type that excludes common falsy values (false, 0, '', null, undefined) - Updated `getAll` to return `undefined` when any signal value is falsy (using `!value`) - Refactored ~30 call sites to combine `enabled` checks with other signal checks into single `getAll` calls - This allows patterns like `effect.getAll([this.enabled, this.value])` to replace separate checks https://claude.ai/code/session_01Ppv4X7gPtpzQTCzabuZzYX
WalkthroughThis pull request refactors multiple modules in the publish and watch subsystems to consolidate value retrieval patterns. Individual 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@js/hang/src/publish/broadcast.ts`:
- Around line 60-61: The current check only returns when path === undefined, but
effect.get(this.path) can now return null and that null may reach
connection.publish; update the guard around the path obtained from
effect.get(this.path) (the local variable named path in the method where you
call connection.publish) to treat both null and undefined as missing (e.g., use
a nullish check like path == null or path === null || path === undefined) and
return early to preserve the previous non-null behavior before calling
connection.publish.
In `@js/signals/src/index.ts`:
- Around line 421-432: The runtime check in getAll uses `if (!value)` which
wrongly treats `0`, `NaN`, `0n`, etc. as falsy and narrows values more than the
Falsy/Truthy types; change the check to only reject null/undefined (e.g. `if
(value === undefined || value === null) return undefined;`) so GetterType/Truthy
semantics are preserved; update the check in getAll (and any related helper)
instead of using `!value`.
🧹 Nitpick comments (1)
js/hang/src/publish/source/file.ts (1)
21-24: Putenabledfirst ingetAllto short-circuit earlier.With the current order,
fileis subscribed even when disabled, so file changes can rerun the effect while decoding is off. Reordering avoids that extra churn.♻️ Suggested reorder
- const values = effect.getAll([this.file, this.enabled]); + const values = effect.getAll([this.enabled, this.file]); if (!values) return; - const [file] = values; + const [_, file] = values;
| const path = effect.get(this.path); | ||
| if (path === undefined) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard against null path values explicitly.
Now that path is no longer part of getAll, null would slip past path === undefined and can reach connection.publish, which could throw. Consider guarding both null and undefined to preserve the previous “non-null” behavior.
🔧 Suggested fix
- const path = effect.get(this.path);
- if (path === undefined) return;
+ const path = effect.get(this.path);
+ if (path == null) return;🤖 Prompt for AI Agents
In `@js/hang/src/publish/broadcast.ts` around lines 60 - 61, The current check
only returns when path === undefined, but effect.get(this.path) can now return
null and that null may reach connection.publish; update the guard around the
path obtained from effect.get(this.path) (the local variable named path in the
method where you call connection.publish) to treat both null and undefined as
missing (e.g., use a nullish check like path == null or path === null || path
=== undefined) and return early to preserve the previous non-null behavior
before calling connection.publish.
| // Get the values of multiple signals, returning undefined if any are falsy. | ||
| getAll<S extends readonly Getter<unknown>[]>( | ||
| signals: [...S], | ||
| ): { [K in keyof S]: NonNullable<GetterType<S[K]>> } | undefined { | ||
| ): { [K in keyof S]: Truthy<GetterType<S[K]>> } | undefined { | ||
| const values: unknown[] = []; | ||
| for (const signal of signals) { | ||
| const value = this.get(signal); | ||
| if (value == null) return undefined; | ||
| if (!value) return undefined; | ||
| values.push(value); | ||
| } | ||
| return values as { [K in keyof S]: NonNullable<GetterType<S[K]>> }; | ||
| return values as { [K in keyof S]: Truthy<GetterType<S[K]>> }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cd js/signals && find . -name "*.ts" -o -name "*.tsx" | head -20Repository: moq-dev/moq
Length of output: 138
🏁 Script executed:
cd js/signals && cat -n src/index.ts | sed -n '415,440p'Repository: moq-dev/moq
Length of output: 1022
🏁 Script executed:
cd js/signals && grep -n "type Falsy\|type Truthy" src/index.ts | head -20Repository: moq-dev/moq
Length of output: 146
🏁 Script executed:
cd js/signals && rg "Falsy|Truthy" --type ts -B 2 -A 2Repository: moq-dev/moq
Length of output: 786
Runtime truthiness is stricter than the Falsy type definition.
!value also treats NaN and 0n as falsy, which aren't included in Falsy/Truthy. If only the explicit falsy values should be excluded, use explicit comparisons:
Suggested fix
- if (!value) return undefined;
+ if (value === false || value === 0 || value === "" || value === null || value === undefined) {
+ return undefined;
+ }Alternatively, document that the function also excludes NaN and 0n.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Get the values of multiple signals, returning undefined if any are falsy. | |
| getAll<S extends readonly Getter<unknown>[]>( | |
| signals: [...S], | |
| ): { [K in keyof S]: NonNullable<GetterType<S[K]>> } | undefined { | |
| ): { [K in keyof S]: Truthy<GetterType<S[K]>> } | undefined { | |
| const values: unknown[] = []; | |
| for (const signal of signals) { | |
| const value = this.get(signal); | |
| if (value == null) return undefined; | |
| if (!value) return undefined; | |
| values.push(value); | |
| } | |
| return values as { [K in keyof S]: NonNullable<GetterType<S[K]>> }; | |
| return values as { [K in keyof S]: Truthy<GetterType<S[K]>> }; | |
| } | |
| // Get the values of multiple signals, returning undefined if any are falsy. | |
| getAll<S extends readonly Getter<unknown>[]>( | |
| signals: [...S], | |
| ): { [K in keyof S]: Truthy<GetterType<S[K]>> } | undefined { | |
| const values: unknown[] = []; | |
| for (const signal of signals) { | |
| const value = this.get(signal); | |
| if (value === false || value === 0 || value === "" || value === null || value === undefined) { | |
| return undefined; | |
| } | |
| values.push(value); | |
| } | |
| return values as { [K in keyof S]: Truthy<GetterType<S[K]>> }; | |
| } |
🤖 Prompt for AI Agents
In `@js/signals/src/index.ts` around lines 421 - 432, The runtime check in getAll
uses `if (!value)` which wrongly treats `0`, `NaN`, `0n`, etc. as falsy and
narrows values more than the Falsy/Truthy types; change the check to only reject
null/undefined (e.g. `if (value === undefined || value === null) return
undefined;`) so GetterType/Truthy semantics are preserved; update the check in
getAll (and any related helper) instead of using `!value`.
getAllchecks for truthy instead of being lame and checking for null.