Share via


Tipi di dati definiti dall'utente in Bicep

Informazioni su come usare i tipi di dati definiti dall'utente in Bicep.

Per usare questa funzionalità è necessaria l'interfaccia della riga di comando Bicep versione 0.12.X o successiva .

Sintassi del tipo di dati definito dall'utente

È possibile usare type l'istruzione per definire i tipi di dati definiti dall'utente. Inoltre, è anche possibile usare espressioni di tipo in alcune posizioni per definire tipi personalizzati.

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

Nota

L'elemento decorator @allowed è consentito solo nelle istruzioni param. Per dichiarare che una proprietà deve essere uno di un set di valori predefiniti in un'istruzione type o output, utilizzare la sintassi del tipo di unione. La sintassi dei tipi di unione può essere usata anche nelle istruzioni param.

Le espressioni di tipo valide includono:

  • I riferimenti simbolici sono identificatori che fanno riferimento a un tipo di ambiente (ad esempio string o int) o a un simbolo di tipo definito dall'utente dichiarato in un'istruzione type:

    // Bicep data type reference
    type myStringType = string
    
    // user-defined type reference
    type myOtherStringType = myStringType
    
  • I valori letterali primitivi, inclusi stringhe, interi e booleani, sono espressioni di tipo valide. Ad esempio:

    // 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
    
  • I tipi di matrice possono essere dichiarati tramite suffisso [] a qualsiasi espressione di tipo valida:

    // 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)[]
    
  • I tipi di oggetto contengono zero o più proprietà tra parentesi graffe:

    type storageAccountConfigType = {
      name: string
      sku: string
    }
    

    Ogni proprietà in un oggetto è costituita da chiave e valore. La chiave e il valore sono separati da due punti :. La chiave può essere qualsiasi stringa (i valori che non sarebbero un identificatore valido devono essere racchiusi tra virgolette) e il valore può essere qualsiasi espressione di sintassi di tipo.

    Le proprietà sono obbligatorie a meno che non abbiano un marcatore ? di facoltatività dopo il valore della proprietà. Ad esempio, la proprietà sku nell'esempio seguente è facoltativa:

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

    Gli elementi Decorator possono essere utilizzati sulle proprietà. * può essere usato per far sì che tutti i valori richiedano un vincolo. È comunque possibile definire proprietà aggiuntive quando si usa *. In questo esempio viene creato un oggetto che richiede una chiave di tipo int denominato id, e tutte le altre voci nell'oggetto devono essere un valore stringa di almeno 10 caratteri.

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

    L'esempio seguente illustra come usare la sintassi del tipo di unione per elencare un set di valori predefiniti:

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

    Ricorsione

    I tipi di oggetto possono usare ricorsione diretta o indiretta, purché almeno una parte del percorso verso il punto di ricorsione sia facoltativa. Ad esempio, la definizione myObjectType nell'esempio seguente è valida perché la proprietà recursiveProp ricorsiva diretta è facoltativa:

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

    Tuttavia, la definizione di tipo seguente non sarebbe valida perché nessuno tra level1, level2, level3, level4 o level5 è facoltativo.

    type invalidRecursiveObjectType = {
      level1: {
        level2: {
          level3: {
            level4: {
              level5: invalidRecursiveObjectType
            }
          }
        }
      }
    }
    
  • Gli operatori unari Bicep possono essere usati con valori letterali interi e booleani o riferimenti a simboli letterali di tipo integer o booleano:

    type negativeIntLiteral = -10
    type negatedIntReference = -negativeIntLiteral
    
    type negatedBoolLiteral = !true
    type negatedBoolReference = !negatedBoolLiteral
    
  • Le unioni possono includere un numero qualsiasi di espressioni di tipo letterale. I tipi di unione vengono convertiti nel vincolo allowed-value (valore consentito) in Bicep, quindi solo i valori letterali sono consentiti come membri.

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

Oltre a essere usato nell'istruzione type, le espressioni di tipo possono essere usate anche in queste posizioni per la creazione di tipi di dati definiti dall'utente:

  • Come clausola type di un'istruzione param. Ad esempio:

    param storageAccountConfig {
      name: string
      sku: string
    }
    
  • Dopo : in una proprietà del tipo di oggetto. Ad esempio:

    param storageAccountConfig {
     name: string
      properties: {
        sku: string
      }
    } = {
      name: 'store$(uniqueString(resourceGroup().id)))'
      properties: {
        sku: 'Standard_LRS'
      }
    }
    
  • Prima di [] in un'espressione di tipo matrice. Ad esempio:

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

Un tipico file Bicep per creare un account di archiviazione è simile al seguente:

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 i tipi di dati definiti dall'utente, può essere simile al seguente:

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

Dichiarare il tipo di unione con tag

Per dichiarare un tipo di dati unione con tag personalizzato all'interno di un file Bicep, è possibile inserire un elemento decorator discriminatorio sopra una dichiarazione di tipo definita dall'utente. Per usare questo elemento decorator è necessaria l’interfaccia della riga di comando di Bicep versione 0.21.X o successiva. La sintassi è:

@discriminator('<propertyName>')

L'elemento decorator discriminante accetta un singolo parametro, che rappresenta un nome di proprietà condiviso tra tutti i membri dell'unione. Questo nome di proprietà deve essere un valore letterale stringa obbligatorio per tutti i membri e fa distinzione tra maiuscole e minuscole. I valori della proprietà discriminata nei membri dell'unione devono essere univoci in modo che non fa distinzione tra maiuscole e minuscole.

Nell'esempio seguente viene illustrato come dichiarare un tipo di unione con tag:

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

Il valore del parametro viene convalidato in base al valore della proprietà discriminata. Nell'esempio precedente, se il valore del parametro serviceConfig è di tipo foo, viene sottoposto a convalida usando il tipo FooConfig. Analogamente, se il valore del parametro è di tipo bar, la convalida viene eseguita usando il tipo BarConfig e questo modello continua anche per altri tipi.

Tipi di importazione tra file Bicep (anteprima)

L'interfaccia della riga di comando bicep versione 0.21.X o successiva è necessaria per usare questa funzionalità di importazione in fase di compilazione. Il flag sperimentale compileTimeImports deve essere abilitato dal file di configurazione Bicep.

Solo i tipi di dati definiti dall'utente che contengono l'elemento Decorator @export() possono essere importati in altri modelli. Attualmente, questo elemento decorator può essere usato solo nelle istruzioni type.

L'esempio seguente consente di importare i due tipi di dati definiti dall'utente da altri modelli:

@export()
type myStringType = string

@export()
type myOtherStringType = myStringType

Per altre informazioni, vedere Importare tipi di dati definiti dall'utente.

Passaggi successivi

  • Per un elenco dei tipi di dati Bicep, vedere Tipi di dati.