Learn how to create user-defined data types in Bicep. For system-defined data types, see Data types. Using user-defined data types automatically enables language version 2.0 code generation.
Symbolic references are identifiers that refer to an ambient type (like string or int) or a user-defined type symbol declared in a type statement:
Bicep
// Bicep data type referencetypemyStringType = string// user-defined type referencetypemyOtherStringType = myStringType
Primitive literals, including strings, integers, and Booleans, are valid type expressions. For example:
Bicep
// a string type with three allowed values.typemyStringLiteralType = 'bicep' | 'arm' | 'azure'// an integer type with one allowed valuetypemyIntLiteralType = 10// an boolean type with one allowed valuetypemyBoolLiteralType = true
You can declare array types by appending [] to any valid type expression:
Bicep
// A string type arraytypemyStrStringsType1 = string[]
// A string type array with three allowed valuestypemyStrStringsType2 = ('a' | 'b' | 'c')[]
typemyIntArrayOfArraysType = int[][]
// A mixed-type array with four allowed valuestypemyMixedTypeArrayType = ('fizz' | 42 | {an: 'object'} | null)[]
Object types contain zero or more properties between curly brackets:
Each property in an object consists of a key and a value separated by a colon :. The key can be any string, with nonidentifier values enclosed in quotation marks. The value can be any type of expression.
Properties are required unless they have an optionality marker ? after the property value. For example, the sku property in the following example is optional:
You can use decorators on properties. You can use an asterisk (*) to make all values require a constraint. You can define more properties by using *. This example creates an object that requires a key of type int named id. All other entries in the object must be a string value at least 10 characters long.
Object types can use direct or indirect recursion if at least the leg of the path to the recursion point is optional. For example, the myObjectType definition in the following example is valid because the directly recursive recursiveProp property is optional:
Unions can include any number of literal-typed expressions. Union types are translated into the allowed-value constraint in Bicep, so only literals are permitted as members.
You can use type expressions in the type statement, and you can also use type expressions to create user-defined data types, as shown in the following places:
As the type clause of a param statement. For example:
Decorators are written in the format @expression and are placed above the declarations of the user-defined data type. The following table shows the available decorators for user-defined data types.
Elevate BCP089 from a warning to an error when a property name of a user-defined data type is likely a typo. For more information, see Elevate error level.
Marks the types as secure. The value for a secure type isn't saved to the deployment history and isn't logged. For more information, see Secure strings and objects.
Decorators are in the sys namespace. If you need to differentiate a decorator from another item with the same name, preface the decorator with sys. For example, if your Bicep file includes a variable named description, you must add the sys namespace when you use the description decorator.
You can set minimum and maximum values for integer type. You can set one or both constraints.
Bicep
@minValue(1)
@maxValue(12)typemonthint
Length constraints
You can specify minimum and maximum lengths for string and array types. You can set one or both constraints. For strings, the length indicates the number of characters. For arrays, the length indicates the number of items in the array.
The following example declares two types. One type is for a storage account name that must have 3 to 24 characters. The other type is an array that must have from one to five items.
If you have custom properties that you want to apply to a user-defined data type, add a metadata decorator. Within the metadata, define an object with the custom names and values. The object you define for the metadata can contain properties of any name and type.
You might use this decorator to track information about the data type that doesn't make sense to add to the description.
Bicep
@description('Configuration values that are applied when the application starts.')
@metadata({
source: 'database'contact: 'Web team'
})typesettingsobject
When you provide a @metadata() decorator with a property that conflicts with another decorator, that decorator always takes precedence over anything in the @metadata() decorator. So, the conflicting property within the @metadata() value is redundant and is replaced. For more information, see No conflicting metadata.
By default, declaring an object type in Bicep allows it to accept more properties of any type. For example, the following Bicep is valid but raises a warning of [BCP089]: The property "otionalProperty" is not allowed on objects of type "{ property: string, optionalProperty: null | string }". Did you mean "optionalProperty"?:
The warning informs you that the anObject type doesn't include a property named otionalProperty. Although no errors occur during deployment, the Bicep compiler assumes that otionalProperty is a typo and that you intended to use optionalProperty but misspelled it. Bicep alerts you to the inconsistency.
To escalate these warnings to errors, apply the @sealed() decorator to the object type:
The Azure Resource Manager deployment engine also checks sealed types for other properties. Providing any extra properties for sealed parameters results in a validation error, which causes the deployment to fail. For example:
To declare a custom tagged union data type within a Bicep file, you can place a discriminator decorator above a user-defined type declaration. Bicep CLI version 0.21.X or higher is required to use this decorator. The following example shows how to declare a tagged union data type: