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

FeaturetypevirtualType
Refers to real class?✅ Yes❌ No (just config)
Creates a new class?❌ No✅ Conceptually yes, via DI config
Use caseModify existing class behaviorCreate 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>

🧠 Pro Tip

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.).