8000 [TypeInfo] Add `ArrayShapeType::$sealed` · symfony/symfony@1e70c86 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1e70c86

Browse files
committed
[TypeInfo] Add ArrayShapeType::$sealed
1 parent d768193 commit 1e70c86

File tree

5 files changed

+30
-7
lines changed

5 files changed

+30
-7
lines changed

src/Symfony/Component/TypeInfo/Tests/Type/ArrayShapeTypeTest.php

+10
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ public function testAccepts()
7676

7777
$this->assertTrue($type->accepts(['foo' => true]));
7878
$this->assertTrue($type->accepts(['foo' => true, 'bar' => 'string']));
79+
80+
$type = new ArrayShapeType(['foo' => ['type' => Type::bool()]], sealed: false);
81+
82+
$this->assertTrue($type->accepts(['foo' => true, 'other' => 'string']));
83+
$this->assertTrue($type->accepts(['other' => 'string', 'foo' => true]));
7984
}
8085

8186
public function testToString()
@@ -94,5 +99,10 @@ public function testToString()
9499
'bar' => ['type' => Type::string(), 'optional' => true],
95100
]);
96101
$this->assertSame("array{'bar'?: string, 'foo': bool}", (string) $type);
102+
103+
$type = new ArrayShapeType([
104+
'foo' => ['type' => Type::bool()],
105+
], sealed: false);
106+
$this->assertSame("array{'foo': bool, ...}", (string) $type);
97107
}
98108
}

src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public static function resolveDataProvider(): iterable
7676
// array shape
7777
yield [Type::arrayShape(['foo' => Type::true(), 1 => Type::false()]), 'array{foo: true, 1: false}'];
7878
yield [Type::arrayShape(['foo' => ['type' => Type::bool(), 'optional' => true]]), 'array{foo?: bool}'];
79+
yield [Type::arrayShape(['foo' => Type::bool()], sealed: false), 'array{foo: bool, ...}'];
7980

8081
// object shape
8182
yield [Type::object(), 'object{foo: true, bar: false}'];

src/Symfony/Component/TypeInfo/Type/ArrayShapeType.php

+16-4
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ final class ArrayShapeType extends CollectionType
3131
/**
3232
* @param array<array{type: Type, optional: bool}> $shape
3333
*/
34-
public function __construct(array $shape)
35-
{
34+
public function __construct(
35+
array $shape,
36+
private readonly bool $sealed = true,
37+
) {
3638
$keyTypes = [];
3739
$valueTypes = [];
3840

@@ -66,6 +68,11 @@ public function getShape(): array
6668
return $this->shape;
6769
}
6870

71+
public function isSealed(): bool
72+
{
73+
return $this->sealed;
74+
}
75+
6976
public function accepts(mixed $value): bool
7077
{
7178
if (!\is_array($value)) {
@@ -80,11 +87,12 @@ public function accepts(mixed $value): bool
8087

8188
foreach ($value as $key => $itemValue) {
8289
$valueType = $this->shape[$key]['type'] ?? false;
83-
if (!$valueType) {
90+
91+
if ($valueType && !$valueType->accepts($itemValue)) {
8492
return false;
8593
}
8694

87-
if (!$valueType->accepts($itemValue)) {
95+
if (!$valueType && $this->sealed) {
8896
return false;
8997
}
9098
}
@@ -105,6 +113,10 @@ public function __toString(): string
105113
$items[] = \sprintf('%s: %s', $itemKey, $value['type']);
106114
}
107115

116+
if (!$this->sealed) {
117+
$items[] = '...';
118+
}
119+
108120
return \sprintf('array{%s}', implode(', ', $items));
109121
}
110122
}

src/Symfony/Component/TypeInfo/TypeFactoryTrait.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,13 @@ public static function dict(?Type $value = null): CollectionType
198198
/**
199199
* @param array<array{type: Type, optional?: bool}|Type> $shape
200200
*/
201-
public static function arrayShape(array $shape): ArrayShapeType
201+
public static function arrayShape(array $shape, bool $sealed = true): ArrayShapeType
202202
{
203203
return new ArrayShapeType(array_map(static function (array|Type $item): array {
204204
return $item instanceof Type
205205
? ['type' => $item, 'optional' => false]
206206
: ['type' => $item['type'], 'optional' => $item['optional'] ?? false];
207-
}, $shape));
207+
}, $shape), $sealed);
208208
}
209209

210210
/**

src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ private function getTypeFromNode(TypeNode $node, ?TypeContext $typeContext): Typ
110110
];
111111
}
112112

113-
return Type::arrayShape($shape);
113+
return Type::arrayShape($shape, $node->sealed);
114114
}
115115

116116
if ($node instanceof ObjectShapeNode) {

0 commit comments

Comments
 (0)
0