What is the difference between type and virtualType

Virtual types are a way to inject different dependencies into existing classes without affecting other classes.

For example, the Magento\Framework\Session\Storage class takes a $namespace argument in its constructor, which defaults to the value 'default', and you could use the type definition to change the namespace to 'core'.

<type name="Magento\Framework\Session\Storage">
    <arguments>
        <argument name="namespace" xsi:type="string">core</argument>
    </arguments>
</type>

The above config would make it so that all instances of Magento\Framework\Session\Storage have a namespace of 'core'. Using a virtual type allows for the equivalent of a sub-class to be created, where only the sub-class has the altered argument values.

In the codebase we see the following two configurations:

<virtualType name="Magento\Core\Model\Session\Storage" type="Magento\Framework\Session\Storage">
    <arguments>
        <argument name="namespace" xsi:type="string">core</argument>
    </arguments>
</virtualType>

<type name="Magento\Framework\Session\Generic">
    <arguments>
        <argument name="storage" xsi:type="object">Magento\Core\Model\Session\Storage</argument>
    </arguments>
</type>

The first snippet creates a virtual type for Magento\Core\Model\Session\Storage which alters the namespace, and the second inject the virtual type into Magento\Framework\Session\Generic. This allows Magento\Framework\Session\Generic to be customized without affecting other classes that also declare a dependency on Magento\Framework\Session\Storage


Another way to understand virtual types -

Let's say that you have a class \Class1, which has the following constructor -

public function __construct(\Class2 $argOfClass1){...}

And \Class2 has the following constructor -

public function __construct(\Class3 $argOfClass2){...}

Now, you want to change the type of $argOfClass2 from \Class3 to \Class4, but only when \Class2 is used as $argOfClass1.

The "old" way to do that would be to add the following in di.xml -

<type name="Class1">
    <arguments>
         <argument name="argOfClass1" xsi:type="object">Class5</argument>
    </arguments>
</type>

where \Class5 is the following:

class \Class5 extends \Class2{
    public function __construct(\Class4 $argOfClass2){...}
}

Instead of using this way, you can use the virtual types to accomplish the same, by adding the following to di.xml:

<virtualType name="Class5" type="Class2">
    <arguments>
        <argument name="argOfClass2" xsi:type="string">Class4</argument>
    </arguments>
</virtualType>

<type name="Class1">
    <arguments>
         <argument name="argOfClass1" xsi:type="object">Class5</argument>
    </arguments>
</type>

As you can see, using the virtual type saved you the work of creation of Class5.

For further reference I suggest to read Alan Storm's article regarding virtual types in Magento2 - http://alanstorm.com/magento_2_object_manager_virtual_types/


In the same di.xml file I found that lessFileSourceBase is passed as an argument for lessFileSourceBaseFiltered that is passed as an argument for lessFileSourceBaseSorted that is passed as an argument for type Magento\Framework\Less\File\Collector\Aggregated.

I found no other occurrence of lessFileSourceBase (or lessFileSource ) in an other file except di.xml from the core module. Only in some cache files but those are not important.

I guess if you are not going to use the virtual type in a PHP class, but only in the di xml files then you are not required to make it look like a class name and you can use an alias.

But this is just pure speculation.
It will be "fun" to try to create a class and inject in its constructor an instance of lessFileSourceBase to see how it behaves.