Skip to content

Commit

Permalink
Add initial support for union types
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenvanassche committed May 3, 2024
1 parent fbda346 commit 6075b43
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
11 changes: 8 additions & 3 deletions src/DataPipes/CastPropertiesDataPipe.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Spatie\LaravelData\Casts\IterableItemCast;
use Spatie\LaravelData\Casts\Uncastable;
use Spatie\LaravelData\Enums\DataTypeKind;
use Spatie\LaravelData\Exceptions\CannotCreateData;
use Spatie\LaravelData\Lazy;
use Spatie\LaravelData\Optional;
use Spatie\LaravelData\Support\Creation\CreationContext;
Expand Down Expand Up @@ -87,9 +88,13 @@ protected function cast(
) {
$context = $creationContext->next($property->type->dataClass, $property->name);

return $property->type->kind->isDataObject()
? $context->from($value)
: $context->collect($value, $property->type->iterableClass);
try {
return $property->type->kind->isDataObject()
? $context->from($value)
: $context->collect($value, $property->type->iterableClass);
} catch (CannotCreateData) {
return $value;
}
}

if (
Expand Down
35 changes: 35 additions & 0 deletions tests/CreationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1067,3 +1067,38 @@ public function __invoke(SimpleData $data)
->toBeArray()
->toEqual(['a', 'collection']);
})->skip(fn () => config('data.features.cast_and_transform_iterables') === false);

it('is possible to create an union type data object', function () {
$dataClass = new class () extends Data {
public string|SimpleData $property;
};

expect($dataClass::from(['property' => 'Hello World'])->property)->toBeInstanceOf(SimpleData::class);

$dataClass = new class () extends Data {
public int|SimpleData $property;
};

expect($dataClass::from(['property' => 10])->property)->toBeInt();
expect($dataClass::from(['property' => 'Hello World'])->property)->toBeInstanceOf(SimpleData::class);

$dataClass = new class () extends Data {
public int|SimpleData|Optional|Lazy $property;
};

expect($dataClass::from(['property' => 10])->property)->toBeInt();
expect($dataClass::from(['property' => 'Hello World'])->property)->toBeInstanceOf(SimpleData::class);
expect($dataClass::from(['property' => Lazy::create(fn () => 10)])->property)->toBeInstanceOf(Lazy::class);
expect($dataClass::from([])->property)->toBeInstanceOf(Optional::class);
});

it('is possible to create a union type data collectable', function () {
$dataClass = new class () extends Data {
/** @var array<int|SimpleData> */
public array $property;
};

expect($dataClass::from(['property' => [10, 'Hello World']])->property)->toEqual(
[10, SimpleData::from('Hello World')]
);
})->todo();

0 comments on commit 6075b43

Please sign in to comment.