Leveraging User Defined Types & Lamda Functions
Stephen Tulp
December 19, 2023
4 minutes to read
Introduction
Now that we have the Landing Zone deployed and getting more comfortable with the array of tools and features we have available to us, we can start to look at some of the more advanced features of Bicep. Today we will look at User-Defined Data Types
and Lambda Functions
.
User-Defined Data Types
User-defined types has recently gone GA and is a feature within Bicep that allows for the creation of custom complex objects within a Bicep template that can encapsulate related properties into a reusable element. Being able to define our own data types is a powerful feature that can help us simplify our Bicep code and make it more readable and maintainable.
The example below is an example of a storage account without using user-defined types.
param location string = resourceGroup().location
param storageAccountName string
@allowed([
'Storage'
'StorageV2'
])
param kind string = 'StorageV2'
@allowed([
'Standard_LRS'
'Standard_GRS'
])
param skuName string = 'Standard_GRS'
@allowed([
'Premium'
'Hot'
'Cool'
])
param accessTier string = 'Hot'
resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: storageAccountName
location: location
kind: kind
sku: {
name: skuName
}
properties: {
accessTier: accessTier
}
}
We can do this instead
param location string = resourceGroup().location
type kind = 'Storage' | 'StorageV2'
type skuName = 'Standard_LRS' | 'Standard_GRS'
type accessTier = 'Premium' | 'Hot' | 'Cool'
type storageAccountConfigType = {
name: string
sku: skuName
kind: kind
tier: accessTier
}
param storageAccountConfig storageAccountConfigType
resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: storageAccountConfig.name
location: location
sku: {
name: storageAccountConfig.sku
}
kind: storageAccountConfig.kind
properties: {
accessTier: storageAccountConfig.tier
}
}
You can see how we are able to group together various parameters that make up the storage account into a single object. This makes it easier to read and understand what is being deployed. We can also reuse this object in other parts of the template.
Benefits of User-Defined Data Types
Some of the benefits of using user-defined types, include:
- Reusability: User-defined types can be defined once and reused across multiple Bicep files or within the same file. This promotes code modularity and reduces duplication.
- Abstraction: User-defined types provide a level of abstraction by allowing you to define custom data structures that align with your specific needs and inputs you are expecting.
Lambda Functions
Lambda expressions (or lambda functions) are blocks of code that can be passed as an argument, taking multiple parameters that are restricted to a single line of code.
In Bicep, lambda expression is in this format:
<lambda variable> => <expression>
Lets take a look at a couple of functions that may be useful, filter()
and sort()
Filter
filter(inputArray, lambda expression)
This will filter an array with a custom filtering function. Lets take a look at an example.
var peoples = [
{
name: 'Stephen'
age: 31
}
{
name: 'Trent'
age: 35
}
{
name: 'Cam'
age: 28
}
{
name: 'Paul'
age: 48
}
]
output oldPeople array = filter(peoples, people => people.age >=31)
Based on this we would have Stephen
, Trent
and Paul
in the oldPeople
array.
Sort
sort(inputArray, lambda expression)
This sorts an array with a custom sort function. Lets take a look at an example.
var peoples = [
{
name: 'Stephen'
age: 31
}
{
name: 'Trent'
age: 35
}
{
name: 'Cam'
age: 28
}
{
name: 'Paul'
age: 48
}
]
output peopleByAge array = sort(peoples, (a, b) => a.age < b.age)
Based on this we would have Cam
, Stephen
, Trent
and Paul
in the peopleByAge
array.
Conclusion
As you can see with these different function types and advanced features, you have a lot of control and options to make your Bicep templates more readable, maintainable and reusable. If the syntax or structure seems complicated at first, I suggest using some examples to get a better understanding of how this can be used within your templates.
In preview, User Defined Functions also builds on the extensibility of Bicep and allows you to create custom functions that can be used within your Bicep templates.