In Magento 2, both type and virtualType are used in di.xml for Dependency Injection (DI) configuration—but they serve different purposes.
✅ 1. type: Real Class
📌 What it is:
Used to define configuration for a real, concrete PHP class.
You can set constructor arguments, preferences, or plugins for this class.
🧾 Example:
<type name="Magento\Catalog\Model\Product">
<arguments>
<argument name="custom_helper" xsi:type="object">Vendor\Module\Helper\Data</argument>
</arguments>
</type>
This modifies the actual Magento\Catalog\Model\Product class at runtime.
✅ 2. virtualType: No Class File — Only Configuration
📌 What it is:
Used to create a new DI configuration "template" based on another class (called the parent).
There is no actual PHP class with the virtual type name.
Helps you avoid duplicating code or config.
🧾 Example:
<virtualType name="Vendor\Module\Model\CustomProduct" type="Magento\Catalog\Model\Product">
<arguments>
<argument name="custom_helper" xsi:type="object">Vendor\Module\Helper\Data</argument>
</arguments>
</virtualType>
Then you can use this virtual type like:
$customProduct = $objectManager->create('Vendor\Module\Model\CustomProduct');
Internally, Magento will instantiate Magento\Catalog\Model\Product with the modified arguments from the virtual type config.
🔍 Differences at a Glance
| Feature | type | virtualType |
|---|---|---|
| Refers to real class? | ✅ Yes | ❌ No (just config) |
| Creates a new class? | ❌ No | ✅ Conceptually yes, via DI config |
| Use case | Modify existing class behavior | Create variant of existing class config |
| Class file required? | ✅ Yes | ❌ No |
| Reusable? | Not ideal for reuse | ✅ Great for reusable config |
🔧 Real-World Use Case
Let’s say you want to inject a custom dependency into a class, but reuse the original class logic.
Instead of:
Creating a new class CustomProduct.php that extends Product.
Use:
<virtualType name="Vendor\Module\Model\CustomProduct" type="Magento\Catalog\Model\Product">
<arguments>
<argument name="custom_helper" xsi:type="object">Vendor\Module\Helper\Data</argument>
</arguments>
</virtualType>
Use virtualType when:
You want multiple configurations of the same class.
You need DI flexibility without adding new PHP files.
Use type when:
You want to modify the behavior of an existing real class (e.g., inject new args, add plugins, etc.).