Compartilhar via


Tipos de dados definidos pelo usuário no Bicep

Saiba como usar tipos de dados definidos pelo usuário no Bicep. Para tipos de dados definidos pelo sistema, consulte Tipos de dados.

A CLI do Bicep versão 0.12.X ou superior é necessária para usar esse recurso.

Sintaxe de tipo de dados definido pelo usuário

Você pode usar a instrução type para definir tipos de dados definidos pelo usuário. Além disso, você também pode usar expressões de tipo em alguns locais para definir tipos personalizados.

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

Observação

O @alloweddecorador só é permitido em paraminstruções. Para declarar que uma propriedade deve ser um de um conjunto de valores predefinidos em uma instrução type ou output, use a sintaxe tipo de união. A sintaxe tipo de união também pode ser usada em param instruções.

As expressões de tipo válidas incluem:

  • Referências simbólicas são identificadores que se referem a um tipo de ambiente (como string ou int) ou a um símbolo de tipo definido pelo usuário declarado em uma instrução type:

    // Bicep data type reference
    type myStringType = string
    
    // user-defined type reference
    type myOtherStringType = myStringType
    
  • Literais primitivos, incluindo cadeias de caracteres, inteiros e boolianos, são expressões de tipo válidas. Por exemplo:

    // 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
    
  • Os tipos de matriz podem ser declarados com o sufixo [] para qualquer expressão de tipo válida:

    // 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)[]
    
  • Os tipos de objeto contêm zero ou mais propriedades entre colchetes:

    type storageAccountConfigType = {
      name: string
      sku: string
    }
    

    Cada propriedade em um objeto consiste em chave e valor. A chave e o valor são separados por dois-pontos :. A chave pode ser qualquer cadeia de caracteres (valores que não seriam um identificador válido devem ser colocados entre aspas), e o valor pode ser qualquer tipo de expressão de sintaxe.

    As propriedades são necessárias, a menos que tenham um marcador de opcionalidade ? após o valor da propriedade. Por exemplo, a propriedade sku no seguinte exemplo é opcional:

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

    Decoradores podem ser usados em propriedades. * pode ser utilizado para fazer com que todos os valores exijam uma restrição. Propriedades adicionais ainda podem ser definidas ao usar *. Este exemplo cria um objeto que requer uma chave do tipo int chamada ide que todas as outras entradas no objeto devem ser uma cadeia de caracteres de valor com pelo menos 10 caracteres.

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

    O exemplo a seguir mostra como usar a sintaxe tipo de união para listar um conjunto de valores predefinidos:

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

    Recursão

    Os tipos de objeto podem usar a recursão direta ou indireta, desde que pelo menos a parte do caminho para o ponto de recursão seja opcional. Por exemplo, a definição myObjectType no seguinte exemplo é válida porque a propriedade recursiveProp recursiva diretamente é opcional:

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

    Mas a seguinte definição de tipo não são válidas, pois nem level1, level2, level3, level4 ou level5 são opcionais.

    type invalidRecursiveObjectType = {
      level1: {
        level2: {
          level3: {
            level4: {
              level5: invalidRecursiveObjectType
            }
          }
        }
      }
    }
    
  • Os operadores unários do Bicep podem ser usados com literais inteiros e boolianos ou referências a símbolos inteiros ou boolianos de tipo literal:

    type negativeIntLiteral = -10
    type negatedIntReference = -negativeIntLiteral
    
    type negatedBoolLiteral = !true
    type negatedBoolReference = !negatedBoolLiteral
    
  • As uniões podem incluir qualquer número de expressões de tipo literal. Os tipos de união são convertidos na restrição de valor permitido no Bicep, portanto, somente literais são permitidos como membros.

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

Além de serem usadas na instrução type, as expressões de tipo também podem ser usadas nestes locais para criar tipos de dados definidos pelo usuário:

  • Como a cláusula de tipo de uma instrução param. Por exemplo:

    param storageAccountConfig {
      name: string
      sku: string
    }
    
  • Seguindo o : em uma propriedade de tipo de objeto. Por exemplo:

    param storageAccountConfig {
     name: string
      properties: {
        sku: string
      }
    } = {
      name: 'store$(uniqueString(resourceGroup().id)))'
      properties: {
        sku: 'Standard_LRS'
      }
    }
    
  • Anterior a [] em uma expressão de tipo de matriz. Por exemplo:

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

Um arquivo Bicep típico para criar uma conta de armazenamento é semelhante a:

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'
}

Usando tipos de dados definidos pelo usuário, ele pode ser semelhante a:

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'
}

Declarar o tipo de união marcado

Para declarar um tipo de dados de união com tags personalizadas em um arquivo Bicep, você pode colocar um decorador discriminador acima de uma declaração de tipo definida pelo usuário. A CLI do Bicep versão 0.21.X ou superior é necessária para usar esse decorador. A sintaxe do é:

@discriminator('<propertyName>')

O decorador discriminador usa um único parâmetro, que representa um nome de propriedade compartilhado entre todos os membros da união. Esse nome de propriedade deve ser um literal de cadeia de caracteres obrigatório em todos os membros e diferencia maiúsculas de minúsculas. Os valores dos bens discriminados sobre os membros da união devem ser únicos de forma insensível a maiúsculas e minúsculas.

O exemplo a seguir mostra como declarar um tipo de união marcado:

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

O valor do parâmetro é validado com base no valor da propriedade discriminada. No exemplo anterior, se o valor do parâmetro serviceConfig for do tipo foo, ele passará pela validação usando o tipo FooConfig. Da mesma forma, se o valor do parâmetro for do tipo bar, a validação será executada usando o tipo BarConfig, e esse padrão continuará para outros tipos também.

Importar os tipos entre os arquivos Bicep (Versão prévia)

v CLI do Bicep versão 0.21.X ou superior é necessária para usar esse recurso de importação em tempo de compilação. O sinalizador experimental compileTimeImports deve ser habilitado no arquivo de configuração do Bicep.

Somente os tipos de dados definidos pelo usuário que têm o decorador @export() podem ser importados para outros modelos. Atualmente, esse decorador só pode ser utilizado em instruções type.

O exemplo a seguir habilita você a importar os dois tipos de dados definidos pelo usuário de outros modelos:

@export()
type myStringType = string

@export()
type myOtherStringType = myStringType

Para obter mais informações, consulte Importar tipos de dados definidos pelo usuário.

Próximas etapas

  • Para obter uma lista dos tipos de data do Bicep, consulte Tipos de dados.