Skip to content

Add ArrayElement type#1270

Merged
sindresorhus merged 5 commits intomainfrom
array-element
Oct 14, 2025
Merged

Add ArrayElement type#1270
sindresorhus merged 5 commits intomainfrom
array-element

Conversation

@sindresorhus
Copy link
Owner

Closes #914 (it's stale)

@sindresorhus sindresorhus requested a review from som-sm October 13, 2025 12:45
@claude

This comment was marked as outdated.

Repository owner deleted a comment from claude bot Oct 13, 2025
Repository owner deleted a comment from claude bot Oct 13, 2025
@claude
Copy link

claude bot commented Oct 13, 2025

Code Review: Add ArrayElement type

Overview

This PR adds a new ArrayElement type that extracts element types from arrays and tuples, promoting an internal helper to a public API. The implementation is clean and well-tested.

✅ Strengths

Code Quality

  • Follows conventions: Uses descriptive type parameters, includes .d.ts extensions in imports, and ends with export {}
  • Clean refactoring: Successfully promotes ArrayElement from source/internal/array.d.ts to public API while updating the sole consumer (Exact type)
  • Proper documentation: Excellent JSDoc with clear description, use-cases, examples with //=> comments, cross-references (@see), and @category tag
  • Export management: Correctly added to index.d.ts and readme.md in appropriate category

Test Coverage

  • Comprehensive edge cases: Tests cover basic arrays, tuples, const tuples, mixed types, readonly arrays, empty arrays, union of arrays, function use cases, and critical edge cases (any, never, unknown)
  • Negative tests: Properly validates that non-arrays return never
  • Realistic examples: Function signature test demonstrates practical usage

🔍 Observations

Implementation Difference

The old internal implementation was:

export type ArrayElement<T> = T extends readonly unknown[] ? T[0] : never;

The new public implementation is:

export type ArrayElement<T> = T extends UnknownArray ? T[number] : never;

Key differences:

  1. Correctness improvement: Old version used T[0] (first element only), new uses T[number] (union of all elements) - this is a bug fix
  2. Better abstraction: Uses UnknownArray type alias instead of inline readonly unknown[]
  3. ⚠️ Behavior change: The old implementation was actually incorrect for its documented purpose ("extract element type"). The new implementation correctly returns all element types as a union.

Usage Context

Looking at source/exact.d.ts, the old buggy behavior of T[0] worked by coincidence because Exact uses ArrayElement in a distributed context where the specific index didn't matter. The new correct implementation T[number] is semantically proper and maintains compatibility.

📋 Checklist Against Guidelines

  • ✅ One type per PR
  • ✅ Tests in test-d/ with edge cases (any, never, unknown)
  • ✅ Descriptive type parameters (implicit from constraint)
  • ✅ No * prefix in docs
  • ✅ First doc line matches readme
  • ✅ Use-cases included
  • ✅ Realistic examples with //=> comments
  • @category tag present
  • .d.ts extension used
  • ✅ Added to index.d.ts and readme.md
  • ✅ File ends with export {}
  • ✅ Import paths include .d.ts extension

🎯 Semantic Analysis

Type Behavior

ArrayElement<[1, 2, 3]> // => 1 | 2 | 3 ✅
ArrayElement<string[]>  // => string ✅
ArrayElement<{a: 1}>    // => never ✅

The type correctly:

  • Extracts union of all tuple element types
  • Handles readonly arrays
  • Returns never for non-arrays (type-safe)
  • Works with any/never/unknown as expected

Comparison with Related Types

  • ArrayValues<T>: Similar but doesn't return never for non-arrays (no constraint check). ArrayElement is safer.
  • LastArrayElement<T>: Specialized for last element only
  • IterableElement: Different domain (works with Set, Map, generators)

The documentation correctly cross-references these types with appropriate caveats.

🚀 Performance & Security

  • Performance: Pure type-level, no runtime impact ✅
  • Security: No security concerns for type definitions ✅

💡 Minor Suggestions (Optional)

Test Enhancement

Consider adding a test for arrays with rest elements to document behavior:

expectType<string | number>('' as ArrayElement<[...string[], number]>);

Documentation

The use-cases mention "returns never for non-arrays" as a benefit, but this is also stated in line 10. Consider consolidating to avoid repetition:

/**
Extracts the element type of an array or tuple.

Returns `never` for non-array types, providing type-safety.

Use-cases:
- Type-safe element extraction in generic contexts.
- Better readability than `T[number]` with explicit array validation.
...

But these are very minor - the current docs are already excellent.

✅ Recommendation

APPROVE - This is a high-quality contribution that:

  1. Fixes a bug in the internal helper (T[0] → T[number])
  2. Promotes a useful type to public API
  3. Follows all project conventions perfectly
  4. Has comprehensive tests and documentation
  5. Maintains backward compatibility (via correct semantics)

The PR is ready to merge once tests pass. Great work! 🎉

sindresorhus and others added 3 commits October 13, 2025 23:36
Co-authored-by: Som Shekhar Mukherjee <49264891+som-sm@users.noreply.github.com>
Repository owner deleted a comment from claude bot Oct 13, 2025
Repository owner deleted a comment from claude bot Oct 13, 2025
Repository owner deleted a comment from claude bot Oct 13, 2025
@som-sm
Copy link
Collaborator

som-sm commented Oct 13, 2025

@sindresorhus Should we ask Claude to use details/summary blocks to shorten its output? It feels too much at the moment, I think.

@sindresorhus
Copy link
Owner Author

Already done: cb977aa

@sindresorhus sindresorhus merged commit 2afaa40 into main Oct 14, 2025
7 checks passed
@sindresorhus sindresorhus deleted the array-element branch October 14, 2025 06:54
som-sm added a commit that referenced this pull request Nov 7, 2025
Co-authored-by: Som Shekhar Mukherjee <49264891+som-sm@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants