Array of objects shape inference breaks working code when array length is equal to 1
- Dominant language
- Bicep
- Stars
- 3.6k
- Forks
- 830
- Avg merge
- 1d 21m
- Merged PRs (30d)
- 79
Description
**Bicep version**
0.22.6
**Describe the bug**
I have a `var` that is an array of non-homogeneous objects. Each object contains:
- one or more required properties
- zero or more optional properties
I use the array in a for-loop to create instances of a module. I use the `contains(...)` function in ternary expressions to see if an object has a given optional property or not. An example of this:
```bicep
contains(item, 'optionalProperty') ? item.optionalProperty : null
```
1. When the length of the array of objects is **equal to 1** then Bicep can infer the shape of the objects in the array.
2. When the length of the array of objects is **greater than 1** then Bicep can no longer infer the shape of the objects in the array.
In (1) above Bicep reports an error when trying to construct a ternary expression that checks for optional properties: `The type "object" does not contain property "optionalProperty". Available properties include "requiredProperty".bicep(BCP053)`
In (2) above it works, you can safely check for the optional property.
**To Reproduce**
Steps to reproduce the behavior:
Create a dummy `module.bicep` with the following content:
```bicep
param requiredProperty string
param optionalProperty string?
```
Create a `main.bicep`, use the two sample contents below to view the two different cases:
- The following code snippet works, because the length of the `items` array is greater than one:
```bicep
var items = [
{
requiredProperty: 'required value 1'
optionalProperty: 'optional value'
}
{
requiredProperty: 'required value 2'
}
]
module myModule 'module.bicep' = [for item in items: {
name: 'MODULE-${guid(item.requiredProperty)}'
params: {
requiredProperty: item.requiredProperty
optionalProperty: contains(item, 'optionalProperty') ? item.optionalProperty : null
}
}]
```
The following code does not work, because the length of the array is one, and Bicep can infer the shape of the object in the array:
```bicep
var items = [
{
requiredProperty: 'required value 1'
}
]
module myModule 'module.bicep' = [for item in items: {
name: 'MODULE-${guid(item.requiredProperty)}'
params: {
requiredProperty: item.requiredProperty
optionalProperty: contains(item, 'optionalProperty') ? item.optionalProperty : null
}
}]
```
**Additional context**
Add any other context about the problem here.
Contributor guide
Research direction
Reproduce the issue with Bicep 0.22.6 using the module.bicep and main.bicep examples in the report, comparing arrays of one and multiple objects. Start by tracing how the array element shape is inferred and how contains(item, 'optionalProperty') is checked. Done means both examples compile consistently while preserving the optional-property behavior.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100