Skip to content
This repository was archived by the owner on Sep 1, 2023. It is now read-only.

Commit 9182b9e

Browse files
committed
Add TypeSpec\varray_or_darray<T> and tests
1 parent 46a628b commit 9182b9e

File tree

6 files changed

+126
-14
lines changed

6 files changed

+126
-14
lines changed

src/TypeSpec.hack

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,9 @@ function vec_like_array<Tv>(TypeSpec<Tv> $tsv): TypeSpec<array<Tv>> {
170170
function vector<Tv>(TypeSpec<Tv> $inner): TypeSpec<Vector<Tv>> {
171171
return new __Private\VectorSpec(Vector::class, $inner);
172172
}
173+
174+
function varray_or_darray<Tv>(
175+
TypeSpec<Tv> $inner,
176+
): TypeSpec<varray_or_darray<Tv>> {
177+
return new __Private\VArrayOrDArraySpec($inner);
178+
}

src/TypeSpec/__Private/ArrayKeySpec.hack

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,4 @@ final class ArrayKeySpec extends UnionSpec<arraykey> {
1515
public function __construct() {
1616
parent::__construct('arraykey', new StringSpec(), new IntSpec());
1717
}
18-
19-
<<__Override>>
20-
public function toString(): string {
21-
return 'arraykey';
22-
}
2318
}

src/TypeSpec/__Private/NumSpec.hack

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,4 @@ final class NumSpec extends UnionSpec<num> {
1515
public function __construct() {
1616
parent::__construct('num', new IntSpec(), new FloatSpec());
1717
}
18-
19-
<<__Override>>
20-
public function toString(): string {
21-
return 'num';
22-
}
2318
}

src/TypeSpec/__Private/UnionSpec.hack

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ abstract class UnionSpec<+T> extends TypeSpec<T> {
3333
// try next
3434
}
3535
}
36-
throw
37-
TypeCoercionException::withValue($this->getTrace(), $this->name, $value);
36+
throw TypeCoercionException::withValue(
37+
$this->getTrace(),
38+
$this->name,
39+
$value,
40+
);
3841
}
3942

4043
<<__Override>>
@@ -46,7 +49,15 @@ abstract class UnionSpec<+T> extends TypeSpec<T> {
4649
// try next
4750
}
4851
}
49-
throw
50-
IncorrectTypeException::withValue($this->getTrace(), $this->name, $value);
52+
throw IncorrectTypeException::withValue(
53+
$this->getTrace(),
54+
$this->name,
55+
$value,
56+
);
57+
}
58+
59+
<<__Override>>
60+
public function toString(): string {
61+
return $this->name;
5162
}
5263
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2016, Fred Emmott
3+
* Copyright (c) 2017-present, Facebook, Inc.
4+
* All rights reserved.
5+
*
6+
* This source code is licensed under the MIT license found in the
7+
* LICENSE file in the root directory of this source tree.
8+
*
9+
*/
10+
11+
namespace Facebook\TypeSpec\__Private;
12+
13+
use namespace Facebook\TypeSpec;
14+
15+
final class VArrayOrDArraySpec<T> extends UnionSpec<varray_or_darray<T>> {
16+
public function __construct(private TypeSpec\TypeSpec<T> $inner) {
17+
parent::__construct(
18+
'varray_or_darray',
19+
TypeSpec\darray(TypeSpec\arraykey(), $inner),
20+
TypeSpec\varray($inner),
21+
);
22+
}
23+
24+
<<__Override>>
25+
public function toString(): string {
26+
return 'varray_or_darray<'.$this->inner->toString().'>';
27+
}
28+
}

tests/VArrayOrDArraySpecTest.hack

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) 2016, Fred Emmott
3+
* Copyright (c) 2017-present, Facebook, Inc.
4+
* All rights reserved.
5+
*
6+
* This source code is licensed under the MIT license found in the
7+
* LICENSE file in the root directory of this source tree.
8+
*
9+
*/
10+
11+
namespace Facebook\TypeAssert;
12+
13+
use namespace Facebook\TypeSpec;
14+
use type Facebook\TypeSpec\TypeSpec;
15+
use function Facebook\FBExpect\expect;
16+
17+
final class VArrayOrDArraySpecTest
18+
extends TypeSpecTest<varray_or_darray<mixed>> {
19+
<<__Override>>
20+
public function getTypeSpec(): TypeSpec<varray_or_darray<int>> {
21+
return TypeSpec\varray_or_darray(TypeSpec\int());
22+
}
23+
24+
<<__Override>>
25+
public function getValidCoercions(): vec<(mixed, varray_or_darray<int>)> {
26+
return vec[
27+
tuple(vec[], varray[]),
28+
tuple(vec['123'], varray[123]),
29+
tuple(varray['123'], varray[123]),
30+
tuple(varray[123], varray[123]),
31+
tuple(dict['foo' => '456'], darray['foo' => 456]),
32+
tuple(Vector {123}, varray[123]),
33+
tuple(darray['foo' => 123], darray['foo' => 123]),
34+
tuple(keyset['123'], darray['123' => 123]),
35+
];
36+
}
37+
38+
<<__Override>>
39+
public function getInvalidCoercions(): vec<(mixed)> {
40+
return vec[
41+
tuple(false),
42+
tuple(123),
43+
tuple(varray['foo']),
44+
tuple(vec['foo']),
45+
tuple(keyset['foo']),
46+
tuple(darray[123 => 'foo']),
47+
];
48+
}
49+
50+
<<__Override>>
51+
public function getToStringExamples(
52+
): vec<(TypeSpec<varray_or_darray<mixed>>, string)> {
53+
return vec[
54+
tuple(
55+
TypeSpec\varray_or_darray(TypeSpec\string()),
56+
'varray_or_darray<string>',
57+
),
58+
tuple(TypeSpec\varray_or_darray(TypeSpec\int()), 'varray_or_darray<int>'),
59+
];
60+
}
61+
62+
public function testSubtyping(): void {
63+
$varray = (
64+
(): varray<int> ==>
65+
TypeSpec\varray(TypeSpec\int())->assertType(varray[123])
66+
)();
67+
$darray = (
68+
(): darray<arraykey, int> ==>
69+
TypeSpec\darray(TypeSpec\arraykey(), TypeSpec\int())
70+
->assertType(darray['foo' => 123])
71+
)();
72+
$widened_varray = ((): varray_or_darray<int> ==> $varray)();
73+
$widened_darray = ((): varray_or_darray<int> ==> $darray)();
74+
expect($widened_varray)->toEqual($varray);
75+
expect($widened_darray)->toEqual($darray);
76+
}
77+
}

0 commit comments

Comments
 (0)