Condividi tramite


Tipi di dati definiti dall'utente in Bicep

Informazioni su come creare i tipi di dati definiti dall'utente in Bicep. Per i tipi di dati definiti dal sistema, vedere Tipi di dati.

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

Definire i tipi

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

@<decorator>(<argument>)
type <user-defined-data-type-name> = <type-expression>

L'espressione Decorator @allowed è consentita solo nelle paramistruzioni. Per dichiarare un tipo con un set di valori predefiniti in un oggetto type, usare la sintassi del tipo di unione.

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
    
  • È possibile dichiarare i tipi di matrice aggiungendo [] 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 una chiave e un valore, separati da due punti :. La chiave può essere qualsiasi stringa, con valori nonidentifier racchiusi tra virgolette e il valore può essere qualsiasi tipo di espressione.

    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 usati 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 dei tipi di unione per elencare un set di valori predefiniti:

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

Usare elementi Decorator

Gli elementi Decorator vengono scritti nel formato @expression e vengono posizionati sopra le dichiarazioni del tipo di dati definito dall'utente. La tabella seguente illustra gli elementi Decorator disponibili per i tipi di dati definiti dall'utente.

Decorator Applica a Argomento Descrizione
description tutto string Fornire descrizioni per il tipo di dati definito dall'utente.
discriminator oggetto string Usare questo elemento decorator per assicurarsi che la sottoclasse corretta sia identificata e gestita.
export tutto Nessuno Indica che il tipo di dati definito dall'utente è disponibile per l'importazione da un altro file Bicep.
maxLength array, stringa int Lunghezza massima per i tipi di dati stringa e matrice. Il valore è inclusivo.
maxValue int int Valore massimo per i tipi di dati integer. Questo valore è inclusivo.
metadata tutto oggetto Proprietà personalizzate da applicare ai tipi di dati. Può includere una proprietà description equivalente all'elemento decorator della descrizione.
minLength array, stringa int Lunghezza minima per i tipi di dati stringa e matrice. Il valore è inclusivo.
minValue int int Valore minimo per i tipi di dati Integer. Questo valore è inclusivo.
sealed oggetto Nessuno Elevare BCP089 da un avviso a un errore quando un nome di proprietà di un tipo di dati use-define è probabilmente un errore di digitazione. Per altre informazioni, vedere Elevare il livello di errore.
sicuro stringa, oggetto Nessuno Contrassegna i tipi come sicuri. Il valore di un tipo sicuro non viene salvato nella cronologia di distribuzione e non viene registrato. Per altre informazioni, vedere Proteggere stringhe e oggetti.

I decorator si trovano nello spazio dei nomi sys. Se è necessario distinguere un decorator da un altro elemento con lo stesso nome, anteporre al decorator con sys. Ad esempio, se il file Bicep include una variabile denominata description, è necessario aggiungere lo spazio dei nomi sys quando si usa il decorator descrizione.

Discriminatore

Vedere Tipo di dati Unione con tag.

Descrizione

Aggiungere una descrizione al tipo di dati definito dall'utente. Gli elementi Decorator possono essere usati sulle proprietà. Ad esempio:

@description('Define a new object type.')
type obj = {
  @description('The object ID')
  id: int

  @description('Additional properties')
  @minLength(10)
  *: string
}

Il testo formattato markdown può essere usato per il testo della descrizione.

Esportazione

Usare @export() per condividere il tipo di dati definito dall'utente con altri file Bicep. Per altre informazioni, vedere Esportare variabili, tipi e funzioni.

Vincoli sui numeri interi

È possibile impostare valori minimi e massimi per il tipo integer. È possibile impostare uno o entrambi i vincoli.

@minValue(1)
@maxValue(12)
type month int

Vincoli di lunghezza

È possibile specificare lunghezze minime e massime per le definizioni dei tipi stringa e array. È possibile impostare uno o entrambi i vincoli. Per le stringhe, la lunghezza indica il numero di caratteri. Per le matrici, la lunghezza indica il numero di elementi nell'array.

Nell'esempio seguente vengono dichiarati due tipi. Un tipo è per un nome di account di archiviazione che deve avere 3-24 caratteri. L'altro tipo è una matrice che deve avere da 1 a 5 elementi.

@minLength(3)
@maxLength(24)
type storageAccountName string

@minLength(1)
@maxLength(5)
type appNames array

Metadati UFX

Se si dispone di proprietà personalizzate da applicare a un tipo di dati definito dall'utente, aggiungere un elemento Decorator di metadati. All'interno dei metadati definire un oggetto con i nomi e i valori personalizzati. L'oggetto definito per i metadati può contenere proprietà di qualsiasi nome e tipo.

È possibile usare questo elemento Decorator per tenere traccia delle informazioni sul tipo di dati che non hanno senso aggiungere alla descrizione.

@description('Configuration values that are applied when the application starts.')
@metadata({
  source: 'database'
  contact: 'Web team'
})
type settings object

Quando si fornisce un decorator @metadata() con una proprietà in conflitto con un altro decorator, tale decorator ha sempre la precedenza su qualsiasi elemento nel decorator @metadata(). Pertanto, la proprietà in conflitto all'interno del valore @metadata() è ridondante e verrà sostituita. Per altre informazioni, vedere Nessun metadati in conflitto.

Sealed

Vedere Elevare il livello di errore.

Tipi protetti

È possibile contrassegnare il tipo di dati stringa o oggetto definito dall'utente come sicuro. Il valore di un tipo sicuro non viene salvato nella cronologia di distribuzione e non viene registrato.

@secure()
type demoPassword string

@secure()
type demoSecretObject object

Elevare il livello di errore

Per impostazione predefinita, la dichiarazione di un tipo di oggetto in Bicep consente di accettare proprietà aggiuntive di qualsiasi tipo. Ad esempio, il bicep seguente è valido ma genera un avviso di [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'
}

L'avviso informa che il tipo anObject non include una proprietà denominata otionalProperty. Anche se non si verificano errori durante la distribuzione, il compilatore Bicep presuppone che otionalProperty sia un errore di digitazione, che si intende usare optionalProperty, ma lo ha digitato in modo non corretto e segnalare l'incoerenza.

Per inoltrare questi avvisi agli errori, applicare l'elemento Decorator @sealed() al tipo di oggetto:

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

Per ottenere gli stessi risultati, applicare l'elemento decorator @sealed() alla dichiarazione param:

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

Il motore di distribuzione ARM controlla anche i tipi sealed per verificare la presenza di proprietà aggiuntive. Se si specificano proprietà aggiuntive per i parametri sealed, viene generato un errore di convalida, causando l'esito negativo della distribuzione. Ad esempio:

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

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

Tipo di dati unione con tag

Per dichiarare un tipo di dati unione con tag personalizzati all'interno di un file Bicep, è possibile inserire un’espressione Decorator discriminator 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. Nell'esempio seguente viene illustrato come dichiarare un tipo di dati 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

Per altre informazioni, vedere Tipo di dati unione con tag personalizzati.

Passaggi successivi

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