-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Port TypeScript-ESLint rule consistent-indexed-object-style #79
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
Implement the consistent-indexed-object-style rule that enforces consistent usage of indexed object types in TypeScript. Follow-up task of PR #78. ## Implementation Details - Created new rule in `internal/plugins/typescript/rules/consistent_indexed_object_style/` - Enforces consistent placement of indexed object styles - Supports two configuration modes: "record" (default) and "index-signature" - Detects and prevents circular type references - Registered in TypeScript plugin registry ## Rule Behavior The rule ensures that indexed object types are consistently defined using either Record utility type or index signature syntax. ### Configuration Options - `record` (default): Prefer Record<K, V> utility type - `index-signature`: Prefer index signature syntax { [key: K]: V } ### Invalid Patterns (record mode - default) ```typescript // Index signatures that should use Record interface Foo { [key: string]: any; } type Bar = { [key: string]: any }; type Baz = { [K in string]: any }; ``` ### Valid Patterns (record mode - default) ```typescript type Foo = Record<string, any>; type Bar = Readonly<Record<string, any>>; interface Foo { [key: string]: any; bar: string; } // Mixed OK interface Foo { [key: string]: Foo; } // Circular refs OK ``` ### Invalid Patterns (index-signature mode) ```typescript // Record types that should use index signatures type Foo = Record<string, any>; type Bar = Record<number, string>; ``` ### Valid Patterns (index-signature mode) ```typescript interface Foo { [key: string]: any; } type Bar = { [key: string]: any }; ``` ## Test Coverage - Comprehensive test suite ported from TypeScript-ESLint repository - Valid test cases covering various scenarios - Invalid test cases with expected error detection - Tests include: - Interface declarations with index signatures - Type literals with index signatures - Mapped types - Record type references - Circular type references - Both configuration modes ## References - Rule documentation: https://typescript-eslint.io/rules/consistent-indexed-object-style/ - TypeScript-ESLint source: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts - TypeScript-ESLint tests: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/tests/rules/consistent-indexed-object-style.test.ts - Related PR #78: #78 ## Files Changed - `internal/config/config.go` - Added import and rule registration (2 lines) - `internal/plugins/typescript/rules/consistent_indexed_object_style/consistent_indexed_object_style.go` - Complete rule implementation (~450 lines) - `internal/plugins/typescript/rules/consistent_indexed_object_style/consistent_indexed_object_style_test.go` - Comprehensive test suite (~280 lines) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
🤖 This pull request has been linked to DevBird Task #1140 View the task details and manage the automated development workflow in DevBird. Learn more about DevBird here or the announcement blog post here. |
📋 DevBird Task PromptObjectivePort the TypeScript-ESLint rule Documentation & Resources
Rule DescriptionEnforces consistent usage of type imports. Implementation Requirements
Test Requirements
Success Criteria
This comment was automatically added by DevBird. You can disable this feature in DevBird Settings. |
Pull Request Review: consistent-indexed-object-style RuleSummaryThis PR ports the TypeScript-ESLint rule consistent-indexed-object-style to rslint. The implementation is comprehensive and follows the project's conventions well. Code Quality & Best PracticesStrengths
Issues to Address1. Incomplete Rule Documentation Comment (Line 14)The comment says 'enforces consistent usage of type imports' which is a copy-paste error. Should be: 2. Unused Helper Function (Line 422)The getSourceText helper function is defined but never used. This should either be removed if not needed, or used if it was intended for autofix functionality. 3. Missing Autofix FunctionalityThe rule detects violations but doesn't provide autofixes. Similar rules like consistent_generic_constructors provide fixes. This rule would benefit from autofixes to convert between Record and index signature styles. 4. Duplicate Code (Lines 265-288)isDeeplyReferencingType and isDeeplyReferencingTypeParam are nearly identical and could be consolidated. Potential BugsCritical Issues1. Incomplete Mapped Type Check (Line 139)The canConvertMappedTypeToRecord function may not properly distinguish between:
2. Missing Readonly/Optional Modifier ChecksThe rule doesn't account for readonly or optional modifiers in index signatures. These should be handled or documented as limitations. Performance Considerations
Test CoverageExcellent coverage with edge cases, configuration modes, and various TypeScript patterns. Additional test suggestions:
RecommendationsPriority High
Priority Medium
Priority Low
ConclusionThis is a solid implementation with excellent test coverage. Main concerns are the documentation error, missing autofix functionality, and potential edge cases with mapped types. Recommendation: Request changes to address High priority items before merging. Great work on porting this rule! |
- Use AsPropertySignatureDeclaration() instead of AsPropertySignature() - Use AsMethodSignatureDeclaration() instead of AsMethodSignature() - Use AsTypeParameter() instead of AsTypeParameterDeclaration() - Add type kind check for TypeParameter node These changes fix compilation errors in the consistent-indexed-object-style rule. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Port TypeScript-ESLint rule consistent-indexed-object-styleThank you for this comprehensive PR! The implementation is well-structured and follows the codebase patterns. Here's my detailed review: ✅ Strengths
🐛 Issues Found1. Incorrect Rule Description (Line 14)The comment says "enforces consistent usage of type imports" but should say "enforces consistent usage of indexed object types". // CURRENT (incorrect):
// ConsistentIndexedObjectStyleRule enforces consistent usage of type imports
// SHOULD BE:
// ConsistentIndexedObjectStyleRule enforces consistent usage of indexed object types2. Redundant Node Kind CheckIn multiple listeners (lines 48, 95, 126, 152), you check the node kind twice - once in the listener registration and again inside the handler. // Lines 43-50 - redundant check
ast.KindInterfaceDeclaration: func(node *ast.Node) {
if opts.Style != "record" {
return
}
if node.Kind != ast.KindInterfaceDeclaration { // <- This is redundant
return
}The listener is already registered for that specific kind, so the second check is unnecessary. This pattern appears in all four listeners. 3. Missing Circular Reference Check for Type Literals (Line 90-117)The // Should add before line 114:
// Check for circular references (similar to interface handler)
indexSig := member.AsIndexSignatureDeclaration()
if indexSig == nil {
return
}
// Need to get the parent type alias name for circular check
// This is trickier for type literals without a named parentNote: This is complex because type literals may not have a parent name to check against. You may need to add context tracking or skip this check for anonymous type literals. 4. Unused Function (Line 430-439)The
5. Incomplete Constructor Type Handling (Line 375)The code checks for case ast.KindFunctionType, ast.KindConstructorType:
// For function/constructor types, check parameters and return type
if typeNode.Kind == ast.KindFunctionType {
// ... handles function type
}
// Missing: else if typeNode.Kind == ast.KindConstructorType { ... }🎯 Potential Issues6. Missing readonly Modifier SupportThe rule doesn't appear to handle readonly modifiers on index signatures. Looking at the test cases:
This should work correctly, but consider whether 7. Optional Modifier Support (
|
- Add isCircularTypeReference helper to check for recursive types in type aliases
- Fix failing test case for 'type Foo = { [key: string]: Foo; }'
- Update website/env.d.ts to use preferred Record style
Fixes #79
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The newly added consistent-indexed-object-style rule was enabled by default with error severity. This commit explicitly configures it as a warning to match other TypeScript-ESLint stylistic rules in the codebase and prevent CI failures. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: consistent-indexed-object-style RuleOverall AssessmentThis is a well-implemented PR that successfully ports the TypeScript-ESLint ✅ Strengths1. Excellent Test Coverage
2. Robust Circular Reference DetectionThe implementation correctly identifies and skips circular type references (lines 77-80, 119-122), preventing false positives: if isDeeplyReferencingType(interfaceDecl.Name(), indexSig.Type) {
return
}This is a critical feature that prevents the rule from incorrectly flagging recursive types like 3. Comprehensive Type Checking
4. Proper Option ParsingThe rule correctly handles multiple option formats:
🐛 Potential Issues1. Incorrect Comment in Rule Definition (Line 14)// ConsistentIndexedObjectStyleRule enforces consistent usage of type importsIssue: The comment says "type imports" but should say "indexed object types" Fix: Update to: // ConsistentIndexedObjectStyleRule enforces consistent usage of indexed object types2. Redundant Node Kind ChecksIn multiple listener functions (lines 48-49, 95-96, 136-137, 162-163), there are redundant kind checks: if node.Kind != ast.KindInterfaceDeclaration {
return
}Issue: This check is redundant since the listener is already registered for that specific kind in the Suggestion: Remove these redundant checks for cleaner code, or add a comment explaining if there's a specific reason for the defensive programming. 3. Unused Function (Lines 463-472)func getSourceText(ctx rule.RuleContext, start, end int) string {
// ... implementation
}Issue: This function is defined but never used anywhere in the codebase. Fix: Remove the unused function unless it's planned for future use. 4. Missing Constructor Type HandlingThe case ast.KindFunctionType, ast.KindConstructorType:
if typeNode.Kind == ast.KindFunctionType {
// ... only handles FunctionType
}Issue: Constructor types are listed in the case but not actually handled. Fix: Either remove 5. Mapped Type Edge CaseThe
Impact: Medium - mapped types with modifiers might be incorrectly flagged Example: type Foo = { readonly [K in string]: any }; // Should suggest Readonly<Record<string, any>>
type Bar = { [K in string]?: any }; // Should suggest Partial<Record<string, any>>🔍 Code Quality Observations1. Good Defensive Programming
2. Clear Code Organization
3. Minor: Code DuplicationThe functions Suggestion: Consider consolidating these into a single function or add comments explaining the distinction if there's a semantic difference. ⚡ Performance ConsiderationsPositive:
Consideration:
🔒 Security ConcernsNo security issues identified. The code:
📋 Test QualityExcellent Coverage:
Suggestions:
🎯 RecommendationsHigh Priority:
Medium Priority:
Low Priority:
📝 SummaryVerdict: Approve with minor fixes recommended This is high-quality code that successfully implements the TypeScript-ESLint rule behavior. The implementation is robust, well-tested, and follows Go best practices. The issues identified are minor and mostly cosmetic. The core logic for detecting and reporting violations is sound. Recommended next steps:
Great work on this implementation! The test coverage and edge case handling (especially circular references) are particularly commendable. 🤖 Generated with Claude Code |
Pull Request Review: TypeScript-ESLint consistent-indexed-object-style RuleSummaryThis PR successfully ports the Code Quality & Best PracticesStrengths
Areas for Improvement1. Incorrect Documentation Comment (Line 13)// ConsistentIndexedObjectStyleRule enforces consistent usage of type importsThis should be: // ConsistentIndexedObjectStyleRule enforces consistent usage of indexed object types2. Redundant Kind ChecksIn multiple places, there are redundant kind checks: // Lines 47-49, 94-96, 136-138, 162-164
if node.Kind != ast.KindInterfaceDeclaration {
return
}These checks are unnecessary since the listener is already registered for that specific 3. Unused Helper FunctionThe 4. Potential Performance Concern in Recursive Type CheckingThe func checkTypeReferenceWithDepth(targetName string, typeNode *ast.Node, depth int) bool {
if depth > 100 { // reasonable limit
return false
}
// ... rest of implementation with depth+1 for recursive calls
}Potential Bugs & Issues1. Mapped Type Analysis May Be Too StrictIn if mappedType.Type != nil && isDeeplyReferencingTypeParam(typeParam.Name(), mappedType.Type) {
return false
}This prevents conversion when the mapped type value references the key type parameter (e.g., 2. Missing Edge Cases in isValidRecordKeyTypeThe case ast.KindLiteralType:
literalType := typeNode.AsLiteralTypeNode()
if literalType == nil || literalType.Literal == nil {
return false
}
// Check that literal is string, number, or bigint
switch literalType.Literal.Kind {
case ast.KindStringLiteral, ast.KindNumericLiteral, ast.KindBigIntLiteral:
return true
default:
return false
}3. Circular Reference Detection May Not Cover All CasesThe circular reference detection looks solid for direct references, but consider edge cases like: type Foo = { [key: string]: Bar };
type Bar = Foo; // indirect circular referenceThis is likely acceptable to flag, but worth documenting the intended behavior. Performance ConsiderationsPositive Aspects
Concerns
Security ConcernsNo security issues identified. The code:
Test CoverageExcellent Coverage
Test QualityThe tests are comprehensive and well-organized. They accurately port the TypeScript-ESLint test suite, which is a strong validation of correctness. Missing Test Cases to Consider
Additional ObservationsPositive Changes
Commit HistoryThe commit history shows good iterative development:
This demonstrates proper testing and refinement. RecommendationsHigh Priority
Medium Priority
Low Priority
ConclusionThis is a high-quality PR that successfully ports a non-trivial TypeScript-ESLint rule to rslint. The implementation is robust, well-tested, and follows established patterns. The issues identified are mostly minor and don't block merging, but addressing them would improve code quality and maintainability. Recommendation: Approve with minor suggested improvements. Great work! 🎉 |
## Summary This PR ports the TypeScript-ESLint rule `consistent-return` to rslint, which requires return statements to either always or never specify values. Follow-up task of PR #79. ## Implementation Details - ✅ Created new rule in `internal/plugins/typescript/rules/consistent_return/` - ✅ Enforces consistent return statement patterns across function bodies - ✅ Supports TypeScript-specific features (void/Promise<void> return types) - ✅ Supports `treatUndefinedAsUnspecified` configuration option - ✅ Registered in TypeScript plugin registry ## Rule Behavior The rule ensures that functions either always return a value or never return a value, maintaining consistency across all return statements. ### Configuration Options - `treatUndefinedAsUnspecified` (default: false): When true, treats `return undefined` the same as `return` without a value ### Invalid Patterns (default mode) ```typescript // Mixing return with value and return without value function foo() { if (true) return 1; return; } // Async function with inconsistent returns async function bar() { if (true) return Promise.resolve(1); return; } ``` ### Valid Patterns (default mode) ```typescript // Consistent returns with values function foo() { if (true) return 1; return 2; } // Void functions can have empty returns function bar(): void { if (true) return; return; } // Async functions returning Promise<void> async function baz(): Promise<void> { return; } ``` ## Test Coverage - ✅ Comprehensive test suite ported from TypeScript-ESLint repository - ✅ Valid test cases covering various scenarios (30+ cases) - ✅ Invalid test cases with expected error detection (11+ cases) - Tests include: - Basic function declarations and expressions - Arrow functions - Void and Promise<void> return types - Nested functions - Class methods - treatUndefinedAsUnspecified option - Async functions ## References - Rule documentation: https://typescript-eslint.io/rules/consistent-return/ - TypeScript-ESLint source: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/rules/consistent-return.ts - TypeScript-ESLint tests: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/tests/rules/consistent-return.test.ts - Related PR #79: #79 ## Files Changed - `internal/config/config.go` - Added import and rule registration (2 lines) - `internal/plugins/typescript/rules/consistent_return/consistent_return.go` - Complete rule implementation (~220 lines) - `internal/plugins/typescript/rules/consistent_return/consistent_return_test.go` - Comprehensive test suite (~160 lines) ## Notes This is a draft PR. The core functionality is implemented and comprehensive tests have been added. All test cases from the TypeScript-ESLint implementation have been ported. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
## Summary This PR ports the TypeScript-ESLint rule `consistent-return` to rslint, which requires return statements to either always or never specify values. Follow-up task of PR #79. ## Implementation Details - ✅ Created new rule in `internal/plugins/typescript/rules/consistent_return/` - ✅ Enforces consistent return statement patterns across function bodies - ✅ Supports TypeScript-specific features (void/Promise<void> return types) - ✅ Supports `treatUndefinedAsUnspecified` configuration option - ✅ Registered in TypeScript plugin registry ## Rule Behavior The rule ensures that functions either always return a value or never return a value, maintaining consistency across all return statements. ### Configuration Options - `treatUndefinedAsUnspecified` (default: false): When true, treats `return undefined` the same as `return` without a value ### Invalid Patterns (default mode) ```typescript // Mixing return with value and return without value function foo() { if (true) return 1; return; } // Async function with inconsistent returns async function bar() { if (true) return Promise.resolve(1); return; } ``` ### Valid Patterns (default mode) ```typescript // Consistent returns with values function foo() { if (true) return 1; return 2; } // Void functions can have empty returns function bar(): void { if (true) return; return; } // Async functions returning Promise<void> async function baz(): Promise<void> { return; } ``` ## Test Coverage - ✅ Comprehensive test suite ported from TypeScript-ESLint repository - ✅ Valid test cases covering various scenarios (30+ cases) - ✅ Invalid test cases with expected error detection (11+ cases) - Tests include: - Basic function declarations and expressions - Arrow functions - Void and Promise<void> return types - Nested functions - Class methods - treatUndefinedAsUnspecified option - Async functions ## Test Plan - [ ] CI tests pass - [ ] Manual testing with example code - [ ] Integration with existing linter setup ## References - Rule documentation: https://typescript-eslint.io/rules/consistent-return/ - TypeScript-ESLint source: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/rules/consistent-return.ts - TypeScript-ESLint tests: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/tests/rules/consistent-return.test.ts - Related PR #79: #79 ## Files Changed - `internal/config/config.go` - Added import and rule registration (2 lines) - `internal/plugins/typescript/rules/consistent_return/consistent_return.go` - Complete rule implementation (~220 lines) - `internal/plugins/typescript/rules/consistent_return/consistent_return_test.go` - Comprehensive test suite (~160 lines) ## Notes This is a draft PR. The core functionality is implemented and comprehensive tests have been added. All test cases from the TypeScript-ESLint implementation have been ported. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
Summary
This PR ports the TypeScript-ESLint rule
consistent-indexed-object-styleto rslint, which enforces consistent usage of indexed object type definitions in TypeScript.Follow-up task of PR #78.
Implementation Details
internal/plugins/typescript/rules/consistent_indexed_object_style/Rule Behavior
The rule ensures that indexed object types are consistently defined using either Record utility type or index signature syntax.
Configuration Options
record(default): Prefer Record<K, V> utility typeindex-signature: Prefer { [key: K]: V } index signature syntaxInvalid Patterns (record mode - default)
Valid Patterns (record mode - default)
Invalid Patterns (index-signature mode)
Valid Patterns (index-signature mode)
Test Coverage
Test Plan
References
Files Changed
internal/config/config.go- Added import and rule registration (2 lines)internal/plugins/typescript/rules/consistent_indexed_object_style/consistent_indexed_object_style.go- Complete rule implementation (~450 lines)internal/plugins/typescript/rules/consistent_indexed_object_style/consistent_indexed_object_style_test.go- Comprehensive test suite (~280 lines)Notes
This is a draft PR. The core functionality is implemented and comprehensive tests have been added. All test cases from the TypeScript-ESLint implementation have been ported.
🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com