Skip to content

fix: type empty arrays as unknown[] instead of [] - #290

Merged
joetannenbaum merged 3 commits into
laravel:nextfrom
alaminfirdows:fix/array-cast-to-record
Aug 10, 2026
Merged

fix: type empty arrays as unknown[] instead of []#290
joetannenbaum merged 3 commits into
laravel:nextfrom
alaminfirdows:fix/array-cast-to-record

Conversation

@alaminfirdows

@alaminfirdows alaminfirdows commented Jul 25, 2026

Copy link
Copy Markdown

Closes #277

Requires: laravel/surveyor#60

Problem

Model 'array' casts are converted to Record<string, unknown> in generated TypeScript types, even when they represent plain arrays.

Example:

class Event extends Model
{
    protected $casts = [
        'languages' => 'array',
    ];
}

Current output:

languages: Record<string, unknown>

Expected output:

languages: unknown[]

Root Cause

In laravel/surveyor's ModelAnalyzer.php, the resolveCast() method maps all these casts to the same type:

'json', 'encrypted:json', 'encrypted:array', 'encrypted:collection', 'array', 'encrypted:object' 
    => Type::arrayShape(Type::mixed(), Type::mixed()),

This produces Record<string, unknown> for all of them, but 'array', 'encrypted:array', and 'encrypted:collection' represent PHP arrays/lists, not objects.

Fix

1. surveyor (upstream required)

Separate 'array' cast from 'json'/'object' casts:

'json', 'encrypted:json', 'encrypted:object' => Type::arrayShape(Type::mixed(), Type::mixed()),
'array', 'encrypted:array', 'encrypted:collection' => Type::array([]),

Note: This change is in vendor/laravel/surveyor and needs to be made upstream in the surveyor package.

2. wayfinder

Fix empty array type conversion in TypeScriptConverter::convertArrayResult():

if (array_is_list($value)) {
    if (empty($value)) {
        return 'unknown[]'.$nullSuffix;
    }
    // ... rest of logic
}

Before: Type::array([])[] (invalid TypeScript)
After: Type::array([])unknown[] (valid)

Tests

Added tests/Unit/Registry/TypeScriptConverterTest.php with 6 tests:

  • test_array_shape_with_unknown_key_produces_record_type
  • test_array_shape_with_number_key_produces_array_type
  • test_array_shape_with_string_key_produces_record_type
  • test_array_type_produces_array_type
  • test_json_cast_produces_record_type
  • test_array_cast_produces_array_type

All unit tests pass.

@github-actions

Copy link
Copy Markdown

Thanks for submitting a PR!

Note that draft PRs are not reviewed. If you would like a review, please mark your pull request as ready for review in the GitHub user interface.

Pull requests that are abandoned in draft may be closed due to inactivity.

When converting an empty array type (Type::array([])) to TypeScript, the
converter was producing an empty string instead of 'unknown[]'. This
fixes the convertArrayResult method to return 'unknown[]' for empty
arrays, which is the correct TypeScript representation.

This is related to laravel#277 but the full fix for array casts requires an
upstream change in laravel/surveyor to separate 'array' cast from
'json' and 'object' casts in ModelAnalyzer.php.
@alaminfirdows
alaminfirdows force-pushed the fix/array-cast-to-record branch from d8c0d35 to 56191e6 Compare July 25, 2026 01:44
@alaminfirdows
alaminfirdows marked this pull request as ready for review July 25, 2026 01:49
@alaminfirdows
alaminfirdows marked this pull request as draft July 25, 2026 01:51
@alaminfirdows
alaminfirdows marked this pull request as ready for review July 25, 2026 02:32
@joetannenbaum joetannenbaum changed the title fix: convert array cast to unknown[] instead of Record<string, unknown> fix: type empty arrays as unknown[] instead of [] Aug 10, 2026
@joetannenbaum

Copy link
Copy Markdown
Collaborator

Thank you!

@joetannenbaum
joetannenbaum merged commit a95c667 into laravel:next Aug 10, 2026
9 checks passed
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