Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to map generic types? #8

Closed
Ocramius opened this issue Nov 29, 2021 · 2 comments
Closed

How to map generic types? #8

Ocramius opened this issue Nov 29, 2021 · 2 comments

Comments

@Ocramius
Copy link
Contributor

To try out things, I attempted mapping a generic class, where the generic type parameter has not been provided:

<?php

namespace My\App;

use CuyZ\Valinor\Attribute\StaticMethodConstructor;
use CuyZ\Valinor\Mapper\MappingError;
use CuyZ\Valinor\MapperBuilder;

require_once __DIR__ . '/Valinor/vendor/autoload.php';

/** @template T of mixed */
class MyGenericWrapper
{
    /** @var T */
    public mixed $value;
}

$mapper = (new MapperBuilder())
    ->withCacheDir(__DIR__ . '/cache')
    ->mapper();

var_dump($mapper->map(MyGenericWrapper::class, ['value' => 'who knows?']));

This leads to a clear exception:

php example.php 

Fatal error: Uncaught CuyZ\Valinor\Mapper\Exception\InvalidMappingTypeSignature: Could not parse the type `My\App\MyGenericWrapper` that should be mapped: No generic was assigned to the template(s) `T` for the class `My\App\MyGenericWrapper`. in /app/Valinor/src/Mapper/TreeMapperContainer.php:48
Stack trace:
#0 /app/Valinor/src/Mapper/TreeMapperContainer.php(31): CuyZ\Valinor\Mapper\TreeMapperContainer->node('My\\App\\MyGeneri...', Array)
#1 /app/example.php(23): CuyZ\Valinor\Mapper\TreeMapperContainer->map('My\\App\\MyGeneri...', Array)
#2 {main}
  thrown in /app/Valinor/src/Mapper/TreeMapperContainer.php on line 48

The README.md example is clear about generic types where the type parameter has been set:

Valinor/README.md

Lines 258 to 259 in 396f64a

/** @var SomeCollection<SomeClass> */
private SomeCollection $classWithGeneric,

How would one request a MyGenericWrapper<int> from the mapper, as a root de-serialization target?

@Ocramius Ocramius changed the title How to map generic types How to map generic types? Nov 29, 2021
@romm
Copy link
Member

romm commented Nov 29, 2021

Hi @Ocramius, unfortunately type inferring for generics is not handled at all for now, I have to think about it, maybe it could be handled someday.

In the meantime, the following should work:

$mapper->map(MyGenericWrapper::class . '<string>', ['value' => 'who knows?'])

Also, documentation is not finished at all on this topic, but note that you can use the following annotations:

/**
 * @template T of mixed 
 * …or…
 * @template T // mixed is the default type
 *
 * You can also use advanced types:
 * @template T of int|float
 * @template T of SomeClass&SomeOtherClass
 * @template T of string|SomeClass
 * etc…
 */
class MyGenericWrapper
{
    /** @var T */
    public mixed $value;
}

@Ocramius
Copy link
Contributor Author

Thanks for clarifying!

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

No branches or pull requests

2 participants