Skip to content

SOQL: How to use TYPEOF

One polymorphic record branching through a prism into person, organisation, and calendar record types

Across this series you have built up the everyday SOQL toolkit: filtering, sorting, relationships, aggregates, and date logic. The previous article on date functions closed out the time-based patterns. This final article in the core series tackles a more specialised case you will hit the moment you work with polymorphic relationship fields like Task.WhatId.

A polymorphic relationship is a single lookup that can point to different object types from one row to the next, and it needs its own SOQL clause to query cleanly. This article explains what TYPEOF is, when to reach for it, and how it compares to the alternatives, with a worked Apex example you can adapt.

TYPEOF is a SOQL clause for querying polymorphic relationships, where a single reference can point to different object types at runtime.

A quick way to understand this is to compare it with a standard lookup field. A normal lookup points to one fixed object type, while a polymorphic lookup can point to multiple object types and vary row by row.

For example, one Task.WhatId might point to an Opportunity, while another points to a Case. That flexibility is useful, but it creates a query challenge: SOQL cannot always know in advance which type-specific fields are safe to traverse with dot notation.

Task example showing polymorphic WhatId field referencing different object types

Common polymorphic examples include:

  • WhatId and WhoId on Task
  • ParentId on Contact Point objects like ContactPointAddress
  • OwnerId on records that can be owned by either a User or a Queue (for example, Case)

Without TYPEOF, dot notation is usually limited to a small safe subset such as Id, Name, and Type. If you need fields that exist only on certain parent object types, TYPEOF gives you a clear, explicit way to query them.

Use TYPEOF when all of the following are true:

  • You are querying a polymorphic lookup field.
  • You need fields that differ by parent object type.
  • You want one query instead of splitting the logic into multiple queries.

Syntax overview:

  • TYPEOF: The polymorphic field (for example, Parent)
  • WHEN: The object-type branch (for example, Account)
  • THEN: Fields to return for that object type
  • ELSE (optional): Fallback fields when no WHEN branch matches
  • END: Closes the expression

Example:

SELECT Id, Name,
TYPEOF Parent
WHEN Account THEN Id, Name, Description
WHEN Individual THEN Id
ELSE Id
END
FROM ContactPointAddress

Imagine a customer data model where ContactPointAddress.ParentId can point to either an Account or an Individual. You need one dataset for a service process, but the useful fields differ by parent type.

  1. Start with a query that includes one TYPEOF branch per parent type:

    SELECT Id, Name,
    TYPEOF Parent
    WHEN Account THEN Id, Name, Description
    WHEN Individual THEN Id
    END
    FROM ContactPointAddress
    LIMIT 10

    Run it in Developer Console. Rows whose parent is an Individual return Id alone, and the Description column stays blank for them. That blank is the branch working, not a data gap.

  2. In Apex, check the runtime type before using type-specific fields:

    List<ContactPointAddress> addresses = [
    SELECT Id, Name,
    TYPEOF Parent
    WHEN Account THEN Id, Name, Description
    WHEN Individual THEN Id
    END
    FROM ContactPointAddress
    LIMIT 10
    ];
    for (ContactPointAddress address : addresses) {
    if (address.Parent instanceof Account) {
    Account acc = (Account) address.Parent;
    System.debug('Account Description: ' + acc.Description);
    }
    }

    The debug log should show one line per Account-parented row and nothing for the rest. If it throws instead, the instanceof guard has been skipped somewhere.

  3. Keep each branch field list tight so the query stays predictable and easier to maintain.

ApproachBest whenProsTrade-offs
Dot notation onlyYou only need common fields (Id, Name, Type)Simple and readableCannot access type-specific fields reliably
TYPEOFOne polymorphic field, different fields by object typeSingle query, explicit per-type field selectionMore complex query shape; tool output can vary
Multiple queries by typeYou need heavily different logic by typeClear separation and custom logic per typeMore query overhead and orchestration in Apex
  • Forgetting runtime checks in Apex: even with TYPEOF, still guard with instanceof before accessing fields.
  • Missing fallback handling: consider ELSE so unexpected types do not break assumptions.
  • Over-fetching fields: keep THEN field lists minimal for better performance and readability.
  • Tooling confusion: some query tools display polymorphic results differently, so validate with Apex/debug logs when in doubt.
  • Dot-notation assumptions: do not assume type-specific fields are available without TYPEOF.

Performance note: polymorphic queries can still be expensive at scale, so combine good filtering and selectivity practices with careful field selection.

TYPEOF only works in the SELECT clause, and several contexts do not support it at all. Knowing these upfront saves you designing around a query shape that will not compile:

  • Not in WHERE, ORDER BY, GROUP BY, or HAVING. To filter by parent type, use the polymorphic field’s Type qualifier in the WHERE clause instead, for example WHERE What.Type = 'Account'.
  • Not in queries that don’t return objects, such as COUNT() and other aggregate queries.
  • Not supported in Bulk API query jobs or Streaming API PushTopic queries.
  • Can’t be nested inside another TYPEOF, and can’t be combined with functions like FORMAT() in the same SELECT.

See the official TYPEOF reference for the complete list.

🔁 Can I always replace multiple queries with TYPEOF?

Section titled “🔁 Can I always replace multiple queries with TYPEOF?”

Not always. TYPEOF is great when you need one result set with type-specific fields. If each type requires very different business logic, separate queries can still be cleaner.

🧪 Why does my query editor output look incomplete?

Section titled “🧪 Why does my query editor output look incomplete?”

Some tools do not render TYPEOF branches clearly in tabular output. Validate behaviour in Apex, debug logs, or tools that fully support polymorphic result rendering.

🧠 Do I still need instanceof in Apex after using TYPEOF?

Section titled “🧠 Do I still need instanceof in Apex after using TYPEOF?”

Yes. TYPEOF controls what is queried, but your Apex still needs safe runtime checks before you use type-specific fields.

🧭 Is TYPEOF only for Task WhatId and WhoId?

Section titled “🧭 Is TYPEOF only for Task WhatId and WhoId?”

No. It works for supported polymorphic references in Salesforce, including other polymorphic parent relationships.


TYPEOF solves a specific problem: one polymorphic lookup, multiple parent types, and different fields per type in a single SOQL query. Use it when dot notation is not enough, keep each WHEN branch lean, handle unexpected types with ELSE, and pair the query with instanceof checks in Apex before you touch type-specific data.

For further reading, see the official Salesforce TYPEOF documentation. To go deeper, continue with Mastering SOQL in Salesforce: Advanced Techniques and Best Practices, or return to the Discovering SOQL: The Essential Guide for Beginners.