Bicep 中的用户定义的数据类型

了解如何在 Bicep 中使用用户定义的数据类型。

需要安装 Bicep CLI 0.12.X 或更高版本才能使用此功能。

用户定义的数据类型语法

可以使用 type 语句来定义用户定义的数据类型。 此外,还可以在某些位置使用类型表达式来定义自定义类型。

type <user-defined-data-type-name> = <type-expression>

注意

@allowed 修饰器仅在 param 语句上受允许。 要声明某个属性必须是 typeoutput 语句中一组预定义值之一,请使用联合类型语法。 联合类型语法也可以在 param 语句中使用。

有效的类型表达式包括:

  • 符号引用是引用环境类型(如 stringint)或引用在 type 语句中声明的用户定义类型符号的标识符:

    // Bicep data type reference
    type myStringType = string
    
    // user-defined type reference
    type myOtherStringType = myStringType
    
  • 原始字面量,包括字符串、整数和布尔值,都是有效的类型表达式。 例如:

    // a string type with three allowed values.
    type myStringLiteralType = 'bicep' | 'arm' | 'azure'
    
    // an integer type with one allowed value
    type myIntLiteralType = 10
    
    // an boolean type with one allowed value
    type myBoolLiteralType = true
    
  • 可以通过向任何有效的类型表达式添加后缀 [] 来声明数组类型:

    // A string type array
    type myStrStringsType1 = string[]
    // A string type array with three allowed values
    type myStrStringsType2 = ('a' | 'b' | 'c')[]
    
    type myIntArrayOfArraysType = int[][]
    
    // A mixed-type array with four allowed values
    type myMixedTypeArrayType = ('fizz' | 42 | {an: 'object'} | null)[]
    
  • 对象类型在大括号之间包含零个或多个属性:

    type storageAccountConfigType = {
      name: string
      sku: string
    }
    

    对象中的每个属性都包含键和值。 键和值用冒号 : 分隔。 键可以是任何字符串(不是有效标识符的值必须用引号括起来),该值可以是任何类型的语法表达式。

    除非在属性值后面具有可选的标记 ?,否则属性是必需的。 例如,以下示例中的 sku 属性是可选的:

    type storageAccountConfigType = {
      name: string
      sku: string?
    }
    

    修饰器可用于属性。 * 可用于使所有值都需要一个常数。 使用 * 时,仍可能会定义其他属性。 此示例会创建一个对象,该对象需要名为 id 的 int 类型的键,并且该对象中的所有其他条目都必须是一个长度至少为 10 个字符的字符串值。

    type obj = {
      @description('The object ID')
      id: int
    
      @description('Additional properties')
      @minLength(10)
      *: string
    }
    

    以下示例演示如何使用联合类型语法列出一组预定义值:

    type obj = {
      level: 'bronze' | 'silver' | 'gold'
    }
    

    递归

    对象类型可以使用直接或间接递归,只要递归点的路径至少有一段是可选的。 例如,以下示例中的 myObjectType 定义是有效的,因为直接递归 recursiveProp 属性是可选的:

    type myObjectType = {
      stringProp: string
      recursiveProp: myObjectType?
    }
    

    但是,以下类型定义无效,因为 level1level2level3level4level5 都不是可选的。

    type invalidRecursiveObjectType = {
      level1: {
        level2: {
          level3: {
            level4: {
              level5: invalidRecursiveObjectType
            }
          }
        }
      }
    }
    
  • Bicep 一元运算符可结合整数和布尔字面量使用,或结合对整数或布尔字面量类型的符号的引用:

    type negativeIntLiteral = -10
    type negatedIntReference = -negativeIntLiteral
    
    type negatedBoolLiteral = !true
    type negatedBoolReference = !negatedBoolLiteral
    
  • 联合可以包含任意数量的字面量类型表达式。 联合类型在 Bicep 中被翻译为允许值约束,因此只有字面量可以作为成员。

    type oneOfSeveralObjects = {foo: 'bar'} | {fizz: 'buzz'} | {snap: 'crackle'}
    type mixedTypeArray = ('fizz' | 42 | {an: 'object'} | null)[]
    

除了用于 type 语句之外,类型表达式还可用于以下位置,以创建用户定义的数据类型:

  • 作为 param 语句的类型子句。 例如:

    param storageAccountConfig {
      name: string
      sku: string
    }
    
  • 在对象类型属性中的 : 之后。 例如:

    param storageAccountConfig {
     name: string
      properties: {
        sku: string
      }
    } = {
      name: 'store$(uniqueString(resourceGroup().id)))'
      properties: {
        sku: 'Standard_LRS'
      }
    }
    
  • 在数组类型表达式中的 [] 之前。 例如:

    param mixedTypeArray ('fizz' | 42 | {an: 'object'} | null)[]
    

用于创建存储帐户的典型 Bicep 文件如下所示:

param location string = resourceGroup().location
param storageAccountName string

@allowed([
  'Standard_LRS'
  'Standard_GRS'
])
param storageAccountSKU string = 'Standard_LRS'

resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: storageAccountSKU
  }
  kind: 'StorageV2'
}

通过使用用户定义的数据类型,它可以如下所示:

param location string = resourceGroup().location

type storageAccountSkuType = 'Standard_LRS' | 'Standard_GRS'

type storageAccountConfigType = {
  name: string
  sku: storageAccountSkuType
}

param storageAccountConfig storageAccountConfigType

resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: storageAccountConfig.name
  location: location
  sku: {
    name: storageAccountConfig.sku
  }
  kind: 'StorageV2'
}

声明标记的联合类型

若要在 Bicep 文件中声明自定义标记联合数据类型,可以在用户定义的类型声明上方放置鉴别器装饰器。 需要安装 Bicep CLI 0.21.X 或更高版本才能使用此修饰器。 语法为:

@discriminator('<propertyName>')

鉴别器装饰器采用单个参数,该参数表示所有联合成员之间的共享属性名称。 此属性名称必须是所有成员上必需的字符串文本,区分大小写。 联合成员上的可区分的属性的值必须是唯一的,并且采用不区分大小的方式。

以下示例演示如何声明标记的联合类型:

type FooConfig = {
  type: 'foo'
  value: int
}

type BarConfig = {
  type: 'bar'
  value: bool
}

@discriminator('type')
type ServiceConfig = FooConfig | BarConfig | { type: 'baz', *: string }

param serviceConfig ServiceConfig = { type: 'bar', value: true }

output config object = serviceConfig

参数值根据可区分的属性值进行验证。 在之前的示例中,如果 serviceConfig 参数值的类型为 foo,则会使用 FooConfig 类型进行验证。 同样,如果参数值为 bar 类型,则会在 BarConfig 类型中执行验证,并且此模式也会继续用于其他类型

在 Bicep 文件之间导入类型(预览版)

需要安装 Bicep CLI 0.21.X 或更高版本才能使用此编译时导入功能。 必须从 Bicep 配置文件启用试验标志 compileTimeImports

只能将承载 @export() 修饰器的用户定义的数据类型导入其他模板。 目前,此修饰器只能用于 type 语句。

以下示例使你能够从其他模板导入两种用户定义的数据类型:

@export()
type myStringType = string

@export()
type myOtherStringType = myStringType

有关详细信息,请参阅 导入用户定义的数据类型

后续步骤

  • 有关 Bicep 数据类型的列表,请参阅数据类型