# Custom Type Variants


> Define reusable object types with context-specific property requirements using custom type variants.



**Announcement**

The **Custom type variants** feature is in **Private Beta**, where we work with early users and customers to test new features and get feedback before making them generally available.

Reach out to [Customer Success](mailto:support@rudderstack.com) if you are interested in enabling this feature for your workspace.

This guide shows you how to define and use custom type variants in your [Data Catalog](https://www.rudderstack.com/docs/rudder-cli/data-catalog-and-tracking-plans/data-catalog/).

## Overview

Custom type variants let you define different property requirements for reusable object types based on a discriminating property value. This feature is particularly useful when an object type needs different validation rules depending on the context in which it is used.

**Success:** Custom type variants work similarly to [Event Rule Variants](https://www.rudderstack.com/docs/rudder-cli/data-catalog-and-tracking-plans/conditional-validation/event-rules/) but are defined at the custom type level rather than the event level. This makes them reusable across multiple events and Tracking Plans.

## Define custom type variants

Using your preferred text editor, add variants to your custom types in the [Custom Types YAML file](https://www.rudderstack.com/docs/rudder-cli/data-catalog-and-tracking-plans/data-catalog/custom-types/#create-custom-types):

### Basic structure

Custom type variants are defined within custom type definitions. See [Variants YAML Reference](https://www.rudderstack.com/docs/rudder-cli/yaml-data-catalog-and-tracking-plans/yaml-conditional-validation/) for the detailed variant specification.

The following snippet is a simplified example to demonstrate the structure. See the [Examples](#examples) section below for real-world use cases with complete implementations.

```yaml
version: rudder/v1
kind: custom-types
metadata:
  name: mycustomtypes
spec:
  types:
    - id: custom_object
      name: "CustomObject"
      type: object
      description: "Object with context-specific requirements"

      # Common properties for all variants
      properties:
        - property: "#property:property_1"
          required: true    # Discriminator property must be required
        - property: "#property:property_2"
          required: false   # Common property that may be required by variants
        - property: "#property:property_3"
          required: false   # Property used in default case

      variants:
        - type: discriminator
          discriminator: "#property:property_1"    # Must match the property defined above
          cases:
            - display_name: "Case A"
              match:
                - "value1"
                - "value2"
              description: "Description of Case A"
              properties:
                - property: "#property:property_2"
                  required: true

            - display_name: "Case B"
              match:
                - "value3"
              description: "Description of Case B"
              properties:
                - property: "#property:property_2"
                  required: true

          # Default case for unmatched values
          default:
            - property: "#property:property_3"
              required: true
```

Each variant definition requires:

- The discriminator type (`type: discriminator`)
- The discriminating property name (`discriminator`)
- One or more cases with:

  - A display name (`display_name`)
  - Match values (`match`)
  - Description (`description`) explaining when this case applies
  - Property requirements (`properties`) specific to this case
- Optional default case (`default`) for when no cases match

**Warning**

The discriminator property must be:

- Defined in the custom type&#39;s properties section
- Marked as required
- Have a type matching your match values (string, boolean, or number)

## Supported discriminator types

You can use the following discriminator types in your custom type variants:

| Type | Description | Example values |
| :----| :----| :----|
| String | Match against text values | `"US"`, `"UK"`, `"Japan"` |
| Boolean | Match true/false conditions | `true`, `false` |
| Number | Match against numeric thresholds | `500`, `1000`, `2000` |

**Info**

Note that for each type:

- You can specify multiple match values in an array
- Values are matched exactly (no range or pattern matching)
- String matches are case-sensitive

## Examples

The following examples show variant definitions for different use cases:

#### String discriminator

**Use Case**: Different address requirements based on country/region

This example shows how to validate different properties based on the country code, with specific requirements for each region:

```yaml
version: rudder/v1
kind: custom-types
metadata:
  name: address_types
spec:
  types:
    - id: address_object
      name: "AddressObject"
      type: object
      description: "Address with region-specific requirements"

      properties:
        - property: "#property:country"
          required: true
        - property: "#property:street_address"
          required: true
        - property: "#property:city"
          required: true
        - property: "#property:postal_code"
        - property: "#property:state_province"
        - property: "#property:prefecture"
        - property: "#property:district"

      variants:
        - type: discriminator
          discriminator: "#property:country"
          cases:
            - display_name: "US Address"
              match:
                - "US"
                - "USA"
                - "United States"
              description: "US address format with state and ZIP"
              properties:
                - property: "#property:state_province"
                  required: true
                - property: "#property:postal_code"
                  required: true

            - display_name: "UK Address"
              match:
                - "UK"
                - "GB"
                - "United Kingdom"
              description: "UK address format with postcode"
              properties:
                - property: "#property:postal_code"
                  required: true

            - display_name: "Japan Address"
              match:
                - "JP"
                - "Japan"
              description: "Japanese address format with prefecture"
              properties:
                - property: "#property:prefecture"
                  required: true
                - property: "#property:district"
                  required: false

          default:
            - property: "#property:postal_code"
              required: false
```

#### Key takeaways
- Uses string-based country code discrimination
- Handles multiple country codes per case (for example, `US`, `USA`, `United States`)
- Shows region-specific address requirements
- Includes optional fields like district for specific regions

#### Category discriminator

**Use Case**: Different product attributes based on category

This example shows how to validate different properties based on the product category:

```yaml
version: rudder/v1
kind: custom-types
metadata:
  name: product_types
spec:
  types:
    - id: product_object
      name: "ProductObject"
      type: object
      description: "Product with category-specific attributes"

      properties:
        - property: "#property:product_id"
          required: true
        - property: "#property:product_name"
          required: true
        - property: "#property:category"
          required: true
        - property: "#property:price"
          required: true
        - property: "#property:size"
        - property: "#property:color"
        - property: "#property:material"
        - property: "#property:brand"
        - property: "#property:model"
        - property: "#property:screen_size"
        - property: "#property:storage_capacity"
        - property: "#property:author"
        - property: "#property:isbn"
        - property: "#property:page_count"

      variants:
        - type: discriminator
          discriminator: "#property:category"
          cases:
            - display_name: "Clothing & Apparel"
              match:
                - "clothing"
                - "apparel"
                - "fashion"
                - "shoes"
                - "accessories"
              description: "Clothing items with size, color, material"
              properties:
                - property: "#property:size"
                  required: true
                - property: "#property:color"
                  required: true
                - property: "#property:material"
                  required: false
                - property: "#property:brand"
                  required: true

            - display_name: "Electronics"
              match:
                - "electronics"
                - "computers"
                - "phones"
                - "tablets"
                - "gadgets"
              description: "Electronic devices with technical specs"
              properties:
                - property: "#property:brand"
                  required: true
                - property: "#property:model"
                  required: true
                - property: "#property:screen_size"
                  required: false
                - property: "#property:storage_capacity"
                  required: false

            - display_name: "Books & Literature"
              match:
                - "books"
                - "ebooks"
                - "literature"
                - "textbooks"
              description: "Books with author and publishing details"
              properties:
                - property: "#property:author"
                  required: true
                - property: "#property:isbn"
                  required: false
                - property: "#property:page_count"
                  required: false

          default:
            - property: "#property:brand"
              required: false
```

#### Key takeaways
- Uses category-based discrimination
- Shows different property sets for each product type
- Handles optional technical specifications
- Demonstrates category-specific validation rules
- Includes default case for brand property

#### Account type discriminator

**Use Case**: Different profile requirements based on account type

This example shows how to validate different properties based on the user's account type:

```yaml
version: rudder/v1
kind: custom-types
metadata:
  name: user_profile_types
spec:
  types:
    - id: user_profile_object
      name: "UserProfileObject"
      type: object
      description: "User profile with subscription-based requirements"

      properties:
        - property: "#property:user_id"
          required: true
        - property: "#property:email"
          required: true
        - property: "#property:account_type"
          required: true
        - property: "#property:first_name"
        - property: "#property:last_name"
        - property: "#property:company_name"
        - property: "#property:job_title"
        - property: "#property:phone_number"
        - property: "#property:billing_address"
        - property: "#property:tax_id"
        - property: "#property:contract_start_date"
        - property: "#property:account_manager"

      variants:
        - type: discriminator
          discriminator: "#property:account_type"
          cases:
            - display_name: "Individual Account"
              match:
                - "individual"
                - "personal"
                - "consumer"
              description: "Personal individual accounts"
              properties:
                - property: "#property:first_name"
                  required: true
                - property: "#property:last_name"
                  required: true
                - property: "#property:phone_number"
                  required: false

            - display_name: "Enterprise Account"
              match:
                - "enterprise"
                - "premium"
                - "platinum"
              description: "Enterprise accounts with full details"
              properties:
                - property: "#property:company_name"
                  required: true
                - property: "#property:job_title"
                  required: true
                - property: "#property:phone_number"
                  required: true
                - property: "#property:billing_address"
                  required: true
                - property: "#property:tax_id"
                  required: true
                - property: "#property:contract_start_date"
                  required: true
                - property: "#property:account_manager"
                  required: true

          default:
            - property: "#property:first_name"
              required: false
            - property: "#property:last_name"
              required: false
```

#### Key takeaways
- Uses account type discrimination
- Shows progressive property requirements (individual &gt; business &gt; enterprise)
- Demonstrates enterprise-specific fields like contract details
- Includes comprehensive profile validation with default case
- Shows how to handle optional vs. required fields per account type

## Best practices

Follow these best practices when defining custom type variants:

- **Discriminator selection**
  - Choose properties that clearly indicate different contexts
  - Ensure the discriminator property is always available
  - Use simple, predictable property values

- **Case definition**
  - Use clear, descriptive display names
  - Group related match values in the same case
  - Include helpful descriptions

- **Property requirements**
  - Include only relevant properties for each case
  - Consider required vs. optional carefully
  - Use default case for common requirements

- **Validation**
  - Test all variant cases
  - Verify property references
  - Check for edge cases

## Validate and deploy variants

To update your custom types with the newly-added variants, make sure to [validate and deploy the changes](https://www.rudderstack.com/docs/rudder-cli/data-catalog-and-tracking-plans/data-catalog/custom-types/#validate-and-deploy-custom-types) using Rudder CLI.

## Reference custom types in properties

Once defined, you can use custom types with variants in your properties:

```yaml
version: rudder/v1
kind: properties
metadata:
  name: integration_properties
spec:
  properties:
    - id: customer_profile
      name: "customer_profile"
      type: "#custom-type:user_profile_object"
      description: "Customer profile information"
    - id: purchased_product
      name: "purchased_product"
      type: "#custom-type:product_object"
      description: "Product that was purchased"
    - id: shipping_address
      name: "shipping_address"
      type: "#custom-type:address_object"
      description: "Where to ship the order"
```

You can then reference these properties in your [Tracking Plan](https://www.rudderstack.com/docs/rudder-cli/data-catalog-and-tracking-plans/tracking-plans/create/#define-tracking-plans):

```yaml
version: rudder/v1
kind: tracking-plan
metadata:
  name: integrated_tracking_plan
spec:
  id: integrated_plan
  display_name: "Integrated Plan with Custom Types"
  description: "Tracking plan demonstrating custom type usage"
  rules:
    - type: event_rule
      id: purchase_completed_rule
      event: "#event:purchase_completed"
      additional_properties: false

      properties:
        - property: "#property:customer_profile"
          required: true
        - property: "#property:purchased_product"
          required: true
        - property: "#property:shipping_address"
          required: true
```

## See also

- [Event Rule Variants](https://www.rudderstack.com/docs/rudder-cli/data-catalog-and-tracking-plans/conditional-validation/event-rules/)
- [Conditional Validation YAML Reference](https://www.rudderstack.com/docs/rudder-cli/yaml-data-catalog-and-tracking-plans/yaml-conditional-validation/)
- Automated validation and deployment using [CLI-based Workflows](https://www.rudderstack.com/docs/rudder-cli/github-actions/)

<br />

