-
Notifications
You must be signed in to change notification settings - Fork 539
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
fix: remove index signature from base request #2923
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis pull request enhances error handling in the Changes
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
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: 0
🧹 Nitpick comments (1)
packages/xrpl/src/client/index.ts (1)
346-346
: Good defensive programming improvement.This change improves code safety by first checking if the
account
property exists in the request object before checking its type. This pattern prevents potential TypeErrors when the property doesn't exist, especially important after removing the index signature from theBaseRequest
interface (as mentioned in the PR objectives).The code now properly handles the case where a request doesn't include an
account
property, ensuring more robust error handling.According to the ESLint configuration, you should use single quotes instead of double quotes:
- "account" in req && typeof req.account === 'string' + 'account' in req && typeof req.account === 'string'🧰 Tools
🪛 ESLint
[error] 346-346: Replace
"account"
with'account'
(prettier/prettier)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/xrpl/src/client/index.ts
(1 hunks)packages/xrpl/src/models/methods/baseMethod.ts
(0 hunks)
💤 Files with no reviewable changes (1)
- packages/xrpl/src/models/methods/baseMethod.ts
🧰 Additional context used
🪛 ESLint
packages/xrpl/src/client/index.ts
[error] 346-346: Replace "account"
with 'account'
(prettier/prettier)
I'm a bit confused as to what problem this is solving... Can you provide an example? |
Here is a quick and dirty example: https://github.com/interc0der/xrpl-example import type * as xrpl from 'xrpl'
// Type is not restructured correctly on the AccountChannelsParams
// due to the signature indexing on the base request method
export type AccountChannelsParams = Omit<xrpl.AccountChannelsRequest, 'command'>; |
@interc0der I'm able to run the below snippet without the typescript compiler throwing any warnings (or) errors. It looks like type manipulation is possible in the current version of the code. What exactly is missing?
|
Okay, I found this snippet which is problematic.
|
@interc0der can you add some unit tests which prove the correctness of the |
@ckeshava Unit testing for type utilities has been added within the models test directory. We are checking a few models. It should be noted that Chai / Jest unit testing is not designed to pick up non-runtime issues. |
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.
Some of the tests use the subcommand
key in the Request input. I suspect the original design wanted to accomodate these liberties. Here is an example: https://github.com/XRPLF/xrpl.js/actions/runs/13847785489/job/38914627395?pr=2923#step:9:72
Would you be willing to fix these discrepancies?
Thanks for bringing this to our attention. How did you come across this type-check requirement? What are you using xrpl.js for?
assertType<true>({} as HasCommand) | ||
assertType<true>({} as HasNoCommand) |
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.
I don't understand the intent of these two tests. Are you testing that the empty type {}
is compatible with both HasCommand
and HasNoCommand
? How is this useful?
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.
Well, without an additional dependency, its kind tough the check correct type assertions that are not caught during runtime. Index signature removes type-checking of foreign keys and is not caught during runtime. Trying to write unit tests that are runtime-based is quite difficult for this scenerio.
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.
Hmm, I understand. I see the value of the rest of the tests. I didn't understand the need for these two lines only.
…ubcommand requirement on BasePathFindRequest, required per rippled
The integration testing leverages index signatures in a few cases to iterate through typed keys and assert types. This can be easily fixed by add the type signatures where required, locally. Testing has been cleaned of type errors and the path finding request has been typed with a required subcommand. See here for ref: https://github.com/XRPLF/rippled/blob/67028d6ea609b7ed41666f8c4d96680e292f0865/src/xrpld/rpc/handlers/PathFind.cpp#L40https://github.com/XRPLF/rippled/blob/67028d6ea609b7ed41666f8c4d96680e292f0865/src/xrpld/rpc/handlers/PathFind.cpp#L40 For anyone that is facing a similar issue as documented in this issue (the rare few), here is a workaround type hack to extract the index signature from any type interface.
You can then use the Omit<> and the type structure is as expected.
|
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.
Hello! thanks for your work. I have a few comments regarding the linter and one test case.
I have incorporated my suggestions into this commit: 193490b. Feel free to use it.
@@ -135,10 +135,12 @@ describe('server_state', function () { | |||
key, | |||
) { | |||
assert.equal( | |||
// @ts-expect-error -- non-iterative type |
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.
Why do we need all these declarations?
import type { BaseRequest } from '../../src/models' | ||
|
||
// Helper type assertion function (only for TS, no runtime impact) | ||
function assertType<T>(value: T): void { |
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.
Since value
is unused, we could perhaps use _
?
const validated_ledger = response.result.info.validated_ledger | ||
assert.equal(typeof validated_ledger?.hash, 'string') | ||
for (const key of Object.keys(omit(validated_ledger, 'hash'))) { | ||
// @ts-expect-error -- non-iterative type |
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.
This type of @ts-expect-error statements can be removed.
'string', | ||
) | ||
const state_accounting: StateAccountingFinal & { | ||
[index: string]: unknown |
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.
Why do we need this catch-all type here? I have found that we can iterate over the keys without using this additional key-value pair.
@@ -55,6 +55,8 @@ describe('ledger', function () { | |||
assert.typeOf(ledgerResponse.result.ledger_index, 'number') | |||
|
|||
const ledger = ledgerResponse.result.ledger as Ledger & { | |||
// Add index signature to request to iterate through keys and asset types | |||
[index: string]: unknown |
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.
Similar to my comments in other test files, I don't see the need for this additional kv pair
@interc0der Clarification: Are you trying to remove the
|
High Level Overview of Change
[key: string]: any
) from the baserequest
method's TypeScript interface in the XRPL.js library.Omit<>
andPartial<>
, making it easier for third-party developers to extend or manipulate therequest
type in their own projects.Context of Change
request
method likely used an index signature to allow arbitrary key-value pairs, which provided flexibility but sacrificed type safety and discoverability. For example, a definition likeinterface Request { [key: string]: any }
would allow any string key with any value, making it harder for developers to catch errors at compile time and limiting the utility of TypeScript’s tooling (e.g., autocompletion, refactoring).method: string
,params?: object
). This aligns with TypeScript best practices, as index signatures should only be used when the keys are truly dynamic and unknown ahead of time.Omit<Request, 'params'>
orPartial<Request>
) to customize therequest
type without running into issues caused by the loose index signature.[key: string]: string | number
), but removing it entirely was chosen to enforce stricter typing and better align with the library’s intended usage patterns.Type of Change
(Prevents potential type misuse, though not tied to a specific runtime bug.)
(Assumed non-breaking since existing valid usage should still work with explicit types.)
(Primary intent is to improve type structure, making this a refactor as well.)
Did you update HISTORY.md?
(The change is internal to the type system and transparent to end users interacting with the library’s runtime behavior. It mainly benefits developers working with the typings, so no user-facing HISTORY.md update is needed.)
Test Plan
request
method’s intended usage. If the library has a CI pipeline, it likely caught any downstream type errors introduced by this change.