Определяемые пользователем типы данных в Bicep

Узнайте, как создать определяемые пользователем типы данных в Bicep. Сведения о системных типах данных см. в разделе "Типы данных".

Для использования этой функции требуется интерфейс командной строки Bicep версии 0.12.X или более поздней .

Синтаксис

Инструкцию type можно использовать для создания определяемых пользователем типов данных. Кроме того, можно также использовать выражения типов в некоторых местах для определения пользовательских типов.

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

Декоратор @allowed разрешен только для param инструкций. Чтобы объявить тип с набором предопределенных значений в typeсинтаксисе типа объединения.

Допустимые выражения типов включают:

  • Символьные ссылки — это идентификаторы, ссылающиеся на внешний тип (напримерstring, илиint) или символ определяемого пользователем типа, объявленный в инструкции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?
    }
    

    Декораторы можно использовать для свойств. * можно использовать для создания всех значений, требующих ограничения. При использовании *можно определить дополнительные свойства. В этом примере создается объект, требующий ключа именованного идентификатора типаint, и что все остальные записи в объекте должны быть строковым значением не менее 10 символов.

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

    В следующем примере показано, как использовать синтаксис типа объединения для перечисления набора предопределенных значений:

    type directions = 'east' | 'south' | 'west' | 'north'
    
    type obj = {
      level: 'bronze' | 'silver' | 'gold'
    }
    

    Рекурсия

    Типы объектов могут использовать прямую или непрямую рекурсию, если по крайней мере нога пути к точке рекурсии является необязательной. Например, определение в следующем примере допустимо, myObjectType так как непосредственно рекурсивное свойство является необязательным recursiveProp :

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

    Но следующее определение типа не будет допустимым, так как ни один level1из , level2или level3level4level5 необязательный.

    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@2023-04-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@2023-04-01' = {
  name: storageAccountConfig.name
  location: location
  sku: {
    name: storageAccountConfig.sku
  }
  kind: 'StorageV2'
}

Повышение уровня ошибок

По умолчанию объявление типа объекта в Bicep позволяет принимать дополнительные свойства любого типа. Например, следующий Bicep действителен, но вызывает предупреждение [BCP089] - The property "otionalProperty" is not allowed on objects of type "{ property: string, optionalProperty: null | string }". Did you mean "optionalProperty"?:

type anObject = {
  property: string
  optionalProperty: string?
}
 
param aParameter anObject = {
  property: 'value'
  otionalProperty: 'value'
}

Предупреждение сообщает о том, что тип anObject не содержит свойство с именем otionalProperty. Хотя во время развертывания ошибки не возникают, компилятор Bicep предполагает, что otionalProperty является опечаткой, которую вы намеревались использовать необязательныйProperty, но прописал его, и оповещает вас о несоответствии.

Чтобы передать эти предупреждения в ошибки, примените @sealed() декоратор к типу объекта:

@sealed() 
type anObject = {
  property: string
  optionalProperty?: string
}

Вы получаете те же результаты, применяя @sealed() декоратор к param объявлению:

type anObject = {
  property: string
  optionalProperty: string?
}
 
@sealed() 
param aParameter anObject = {
  property: 'value'
  otionalProperty: 'value'
}

Подсистема развертывания ARM также проверяет запечатанные типы для дополнительных свойств. Предоставление дополнительных свойств для запечатанных параметров приводит к ошибке проверки, что приводит к сбою развертывания. Например:

@sealed()
type anObject = {
  property: string
}

param aParameter anObject = {
  property: 'value'
  optionalProperty: 'value'
}

Тип данных объединения с тегами

Чтобы объявить настраиваемый тип данных объединения тегами в файле Bicep, можно разместить discriminator декоратор над объявлением определяемого пользователем типа. Для использования этого декоратора требуется интерфейс командной строки Bicep версии 0.21.X или более поздней . В следующем примере показано, как объявить тип данных объединения с тегами:

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

Дополнительные сведения см. в разделе "Пользовательский тип данных объединения с тегами".

Импорт типов между файлами Bicep

В другие шаблоны можно импортировать только определяемые пользователем типы данных, которые несут @export() декоратор.

В следующем примере можно импортировать два пользовательских типа данных из других шаблонов:

@export()
type myStringType = string

@export()
type myOtherStringType = myStringType

Дополнительные сведения см. в разделе "Импорт определяемых пользователем типов данных".

Следующие шаги

  • Список типов данных Bicep см. в разделе "Типы данных".