Skip to content
Permalink
Browse files

amending type hinting, fleshing out examples

  • Loading branch information...
SignpostMarv committed Aug 4, 2019
1 parent edfd7a0 commit 3c01fed6b8428d7f2143a28934e3703a91b46173
119 README.md
@@ -12,8 +12,12 @@ Typed Object, a simplified version of [signpostmarv/daft-object](https://github.
```php
use SignpostMarv\DaftTypedObject\Immutable as Base;
use SignpostMarv\DaftTypedObject\Immutable as Base;
/**
* @template-extends Base<array{id:int, name:string}>
* @psalm-type DATA = array{id:int, name:string}
*
* @template-extends Base<DATA, DATA>
*
* @property-read int $id
* @property-read string $name
@@ -39,7 +43,9 @@ class Immutable extends Base
use SignpostMarv\DaftTypedObject\DaftTypedObject as Base;
/**
* @template-extends Base<array{id:int, name:string}>
* @psalm-type DATA = array{id:int, name:string}
*
* @template-extends Base<DATA, DATA>
*
* @property int $id
* @property string $name
@@ -58,4 +64,113 @@ class Mutable extends Base
*/
protected $name;
}
```

### Mutable with `DateTimeImmutable` & nullables
```php
use DateTimeImmutable;
use SignpostMarv\DaftTypedObject\DaftTypedObject as Base;
/**
* @template T as array{id:int, name:string, date:DateTimeImmutable|null}
* @template S as array{id:int, name:string, date:string|null}
*
* @template-extends Base<T, S>
*
* @property-read int $id
* @property-read string $name
* @property-read DateTimeImmutable $date
*/
class MutableWithNullables extends Base
{
const TYPED_PROPERTIES = ['id', 'name', 'date'];
const TYPED_NULLABLE_PROPERTIES = ['date'];
/**
* @var int
*/
protected $id;
/**
* @var string|null
*/
protected $name;
/**
* @var DateTimeImmutable|null
*/
protected $date;
/**
* @template K as key-of<T>
*
* @param K $property
* @param T[K] $value
*
* @return S[K]
*/
public static function PropertyValueToScalarOrNull(
string $property,
$value
) {
/**
* @var T[K]|DateTimeImmutable
*/
$value = $value;
if ($value instanceof DateTimeImmutable) {
/**
* @var S[K]
*/
return (string) $value->format('Y-m-d');
}
/**
* @var S[K]
*/
return parent::PropertyValueToScalarOrNull((string) $property, $value);
}
/**
* @template K as key-of<S>
*
* @param K|'date' $property
* @param S[K] $value
*
* @return T[K]
*/
public static function PropertyScalarOrNullToValue(
string $property,
$value
) {
/**
* @var S[K]|string
*/
$value = $value;
if ('date' === $property && is_string($value)) {
$out = new DateTimeImmutable($value);
} else {
/**
* @var S[K]
*/
$value = $value;
/**
* @var T[K]
*/
$out = parent::PropertyScalarOrNullToValue(
(string) $property,
$value
);
}
/**
* @var T[K]
*/
return $out;
}
}
```
@@ -52,12 +52,16 @@ public function dataProviderPackedImplementations() : array
],
Fixtures\MutableWithNullables::class => [
[
['id' => 1, 'name' => 'foo'],
['id' => 1, 'name' => 'foo'],
[
'id' => 1,
'name' => 'foo',
'date' => new DateTimeImmutable('1970-01-01'),
],
['id' => 1, 'name' => 'foo', 'date' => '1970-01-01'],
],
[
['id' => 1, 'name' => null],
['id' => 1, 'name' => null],
['id' => 1, 'name' => 'foo', 'date' => null],
['id' => 1, 'name' => 'foo', 'date' => null],
],
],
];
@@ -82,40 +86,50 @@ public function dataProviderImplementations() : Generator
/**
* @dataProvider dataProviderImplementations
*
* @template T as array<string, scalar|array|object|null>
* @template K as key-of<T>
* @template S as array<K, scalar|null>
*
* @param class-string<DaftTypedObject> $type
* @param array<string, scalar|array|object|null> $args
* @param array<string, scalar|null> $expected
* @param T $args
* @param S $expected
*/
public function testJsonSerialize(
string $type,
array $args,
array $expected
) : void {
/**
* @var array<string, scalar|null>
* @var S
*/
$jsonified = (new $type($args))->jsonSerialize();
static::assertSame($expected, $jsonified);
/**
* @var array<int, K>
*/
$properties = array_keys($jsonified);
static::assertSame(
$expected,
(new $type(array_combine(array_keys($jsonified), array_map(
/**
* @param scalar|null $value
* @param K $property
* @param S[K] $value
*
* @return scalar|array|object|null
* @return T[K]
*/
function (string $property, $value) use ($type) {
/**
* @var scalar|array|object|null
* @var T[K]
*/
return $type::PropertyScalarOrNullToValue(
$property,
(string) $property,
$value
);
},
array_keys($jsonified),
$properties,
$jsonified
))))->jsonSerialize()
);
@@ -341,6 +355,8 @@ public function testMutableSetSucceeds(
++$value;
} elseif (is_string($value)) {
$value = strrev($value);
} elseif ($value instanceof DateTimeImmutable) {
$value = $value->modify('+1 second');
}
$object->$property = $value;
@@ -9,7 +9,9 @@
use SignpostMarv\DaftTypedObject\Immutable as Base;
/**
* @template-extends Base<array{id:int, name:string}>
* @psalm-type DATA = array{id:int, name:string}
*
* @template-extends Base<DATA, DATA>
*
* @property-read int $id
* @property-read string $name
@@ -9,7 +9,9 @@
use SignpostMarv\DaftTypedObject\DaftTypedObject as Base;
/**
* @template-extends Base<array{id:int, name:string}>
* @psalm-type DATA = array{id:int, name:string}
*
* @template-extends Base<DATA, DATA>
*
* @property int $id
* @property string $name
@@ -6,19 +6,24 @@
namespace SignpostMarv\DaftTypedObject\Fixtures;
use DateTimeImmutable;
use SignpostMarv\DaftTypedObject\DaftTypedObject as Base;
/**
* @template-extends Base<array{id:int, name:string|null}>
* @template T as array{id:int, name:string, date:DateTimeImmutable|null}
* @template S as array{id:int, name:string, date:string|null}
*
* @template-extends Base<T, S>
*
* @property-read int $id
* @property-read string|null $name
* @property-read string $name
* @property-read DateTimeImmutable $date
*/
class MutableWithNullables extends Base
{
const TYPED_PROPERTIES = ['id', 'name'];
const TYPED_PROPERTIES = ['id', 'name', 'date'];
const TYPED_NULLABLE_PROPERTIES = ['name'];
const TYPED_NULLABLE_PROPERTIES = ['date'];
/**
* @var int
@@ -29,4 +34,79 @@ class MutableWithNullables extends Base
* @var string|null
*/
protected $name;
/**
* @var DateTimeImmutable|null
*/
protected $date;
/**
* @template K as key-of<T>
*
* @param K $property
* @param T[K] $value
*
* @return S[K]
*/
public static function PropertyValueToScalarOrNull(
string $property,
$value
) {
/**
* @var T[K]|DateTimeImmutable
*/
$value = $value;
if ($value instanceof DateTimeImmutable) {
/**
* @var S[K]
*/
return (string) $value->format('Y-m-d');
}
/**
* @var S[K]
*/
return parent::PropertyValueToScalarOrNull((string) $property, $value);
}
/**
* @template K as key-of<S>
*
* @param K|'date' $property
* @param S[K] $value
*
* @return T[K]
*/
public static function PropertyScalarOrNullToValue(
string $property,
$value
) {
/**
* @var S[K]|string
*/
$value = $value;
if ('date' === $property && is_string($value)) {
$out = new DateTimeImmutable($value);
} else {
/**
* @var S[K]
*/
$value = $value;
/**
* @var T[K]
*/
$out = parent::PropertyScalarOrNullToValue(
(string) $property,
$value
);
}
/**
* @var T[K]
*/
return $out;
}
}
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="3.4.10@c283f0877d543e7ab738d231ba6a3cdce5e1039a">
<file src="Tests/DaftTypedObjectTest.php">
<InvalidArgument occurrences="1">
<InvalidArgument occurrences="2">
<code>new DateTimeImmutable()</code>
<code>testJsonSerialize</code>
</InvalidArgument>
</file>
</files>

0 comments on commit 3c01fed

Please sign in to comment.
You can’t perform that action at this time.