AsType and IsType functions

Applies to: Canvas apps Model-driven apps Power Pages Power Platform CLI

Checks if a record reference is a specific table type (IsType) and treats the reference as that type (AsType).

Note

PAC CLI pac power-fx commands don't support IsType.

Description

The AsType and IsType functions can be used to convert record references (for example polymorphic lookups in Dataverse) and untyped objects to typed objects that can be used directly.

Record References

Read Understand record references and polymorphic lookups for a broader introduction and more details.

A lookup field usually refers to records in a particular table. Because the table type is well established, access the fields of the lookup using simple dot notation. For example, First( Accounts ).'Primary Contact'.'Full Name' walks from the Accounts table to the Primary Contact record in the Contacts table and extracts the Full Name field.

Microsoft Dataverse also supports polymorphic lookup fields, which can refer to records from a set of tables, as in these examples.

Lookup field Can refer to
Owner Users or Teams
Customer Accounts or Contacts
Regarding Accounts, Contacts, Knowledge Articles, etc.

In canvas-app formulas, use record references to work with polymorphic lookups. Because a record reference can refer to different tables, it's unclear which fields are available at runtime when writing a formula. The Record.Field notation isn't available. Those formulas must adapt to the records that the app encounters when it runs.

The IsType function tests if a record reference refers to a specific table type. The function returns a Boolean TRUE or FALSE.

The AsType function treats a record reference as a specific table type, also known as casting. You can use the result as if it were a record of the table and again use the Record.Field notation to access all of the fields of that record. An error occurs if the reference isn't of the specific type.

Use these functions together to first test the table type of a record and then treat it as a record of that type so that the fields are available:

If( IsType( First( Accounts ).Owner, Users ),
    AsType( First( Accounts ).Owner, Users ).'Full Name',
    AsType( First( Accounts ).Owner, Teams ).'Team Name'
)

These functions are needed only if accessing the fields of a record reference. For example, you can use record references in the Filter function without IsType or AsType:

Filter( Accounts, Owner = First( Users ) )

Similarly, you can use record references with the Patch function:

Patch( Accounts, First( Accounts ), { Owner: First( Teams ) } )

When used in a record context, such as within a Gallery or Edit form control, the global disambiguation operator might be needed to reference the table type. For example, this formula would be effective for a gallery that's displaying a list of contacts where Company Name is a Customer lookup:

If( IsType( ThisItem.'Company Name', Accounts ),
    AsType( ThisItem.'Company Name', Accounts ).'Account Name',
    AsType( ThisItem.'Company Name', Contacts ).'Full Name'
)

For both functions, specify the type through the name of the data source connected to the table. For the formula to work, you must also add a data source to the app for any types that you want to test or cast. For example, you must add the Users table as a data source if you want to use IsType and AsType with an Owner lookup and records from that table. You can add only the data sources that you actually use in your app; you don't need to add all the tables that a lookup could reference.

If the record reference is blank, IsType returns FALSE, and AsType returns blank. All fields of a blank record are also blank.

Untyped Objects

Important

An untyped object from a web API or the [ParseJSON function] needs to be converted to a typed object before it can be used in Power Fx. Options to do this include:

  1. Implicitly type the field at the point it's used. For example, an object is converted to a number if it's used with the + operator, if it can be converted to a number. This option can have unexpected conversions and can't convert records and tables as a whole.
  2. Explicitly type each field individually with the Decimal, Text, DateTime, GUID, and other type constructor functions. This is the most invasive to your formulas as each field must be done separately.
  3. Explicitly type JSON with the second argument to the ParseJSON function. This is an easy option that avoids needing the untyped object.
  4. Explicitly type an untyped object using the AsType function. You can also test type before attempting the conversion with the IsType function.

Syntax

AsType( RecordReference, TableType )

  • RecordReference - Required. A record reference, often a lookup field that can refer to a record in any of multiple tables.
  • TableType - Required. The specific table to which the record should be cast.

AsType( UntypedObject, TypeSpecification )

  • UntypedObject - Required. A record reference, often a lookup field that can refer to a record in any of multiple tables.
  • TypeSpecification - Required. A type name or type specification defined with the Type function.

IsType( RecordReference, TableType )

  • RecordReference - Required. A record reference, often a lookup field that can refer to a record in any of multiple tables.
  • TableType - Required. The specific table for which to test.

IsType( UntypedObject, TypeSpecification )

  • UntypedObject - Required. A record reference, often a lookup field that can refer to a record in any of multiple tables.
  • TypeSpecification - Required. A type name or type specification defined with the Type function.

Examples

Record References

Understand record references and polymorphic lookups contains extensive examples.

  1. Create a blank canvas app for tablets.

  2. On the left-pane, select Data > Add data. And then, add Accounts and Contacts tables.

    Blank app with two data sources: accounts and contacts.

  3. On the left-pane, select + (Insert) > Layout > Blank vertical gallery.

    Insert a gallery control with a blank vertical layout.

  4. Select Connect to data, and then select Contacts as the data source.

  5. Set the gallery's layout to Title and subtitle.

    Open the layout picker from the properties pane.

    Set layout to Title and subtitle.

  6. In the Data pane, open the Title1 list, and then select Full Name.

    Set title value.

  7. Select the Subtitle1 label control.

    Set subtitle value.

  8. Set the Text property of Subtitle1 to this formula:

    If( IsBlank( ThisItem.'Company Name' ), "--",
        IsType( ThisItem.'Company Name', Accounts ),
            "Account: " & AsType( ThisItem.'Company Name', Accounts ).'Account Name',
        "Contact: " & AsType( ThisItem.'Company Name', Contacts ).'Full Name'
    )
    

    Screen is now complete showing accounts and contacts intermixed in the gallery.

    The subtitle in the gallery shows these values:

    • "--" if the 'Company Name' is blank.
    • "Account: " and then the Account Name field from the Accounts table if the Company Name field refers to an account.
    • "Contact: " and then the Full Name field from the Contacts table if the Company Name field refers to a contact.

    Your results might differ because the sample data might have been modified to show more types of results.

Untyped Objects

The following examples show a simple JSON record interpreted in various ways by ParseJSON, AsType, and IsType in the Pac CLI Power Fx REPL.

In this first example, no type information is provided to ParseJSON, so it returns an untyped object.

>> Set( rec, ParseJSON( "{""a"":1}" ) )
rec: <Untyped: Use Value, Text, Boolean, or other functions to establish the type>

The field is implicitly converted to a number when used in a numerical context.

>> 1 + rec.a
2

As an alternative, this example explicitly converts the record to a typed Power Fx record with the second argument to ParseJSON.

>> ParseJSON( "{""a"":1}", Type( {a: Number} ) )
{a:1}

And another alternative, this example explicitly converts the record to a typed Power Fx record using AsType.

>> AsType( ParseJSON( "{""a"":1}" ), Type( {a: Number} ) )
{a:1}

Finally, if we weren't sure, this example tests the type before converting it with the IsType function.

>> IsType( ParseJSON( "{""a"":1}" ), Type( {a: Number} ) )
true