Freigeben über


Benutzerdefinierte Datentypen in Bicep

Hier erfahren Sie, wie Sie benutzerdefinierte Datentypen in Bicep erstellen. Informationen zu vom System definierten Datentypen finden Sie unter Datentypen.

Um diese Funktion nutzen zu können, ist Bicep Version 0.12.X oder höher erforderlich.

Definieren von Typen

Sie können die Anweisung „type“ verwenden, um benutzerdefinierte Datentypen zu erstellen. Darüber hinaus können Sie an einigen Stellen auch Typausdrücke verwenden, um benutzerdefinierte Typen zu definieren.

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

Das @allowed-Decorator-Element ist nur für param-Anweisungen zulässig. Zum Deklarieren eines Typs mit einer Gruppe vordefinierter Werte in type verwenden Sie die Union-Typsyntax.

Zu den gültigen Typausdrücken gehören:

  • Symbolische Verweise sind Bezeichner, die auf einen Ambient-Typ (z.  B. string oder int) oder auf ein deklariertes benutzerdefiniertes Typsymbol in einer „type“-Anweisung verweisen:

    // Bicep data type reference
    type myStringType = string
    
    // user-defined type reference
    type myOtherStringType = myStringType
    
  • Primitive Literale, einschließlich Zeichenfolgen, ganzen Zahlen und Boolesche Werten sind gültige Typausdrücke. Zum Beispiel:

    // 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
    
  • Sie können Arraytypen deklarieren, indem Sie [] an einen beliebigen gültigen Typausdruck anfügen:

    // 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)[]
    
  • Objekttypen enthalten 0 oder mehr Eigenschaften zwischen geschweiften Klammern:

    type storageAccountConfigType = {
      name: string
      sku: string
    }
    

    Jede Eigenschaft in einem Objekt besteht aus einem Schlüssel und einem Wert, getrennt durch einen Doppelpunkt :. Der Schlüssel kann eine beliebige Zeichenfolge sein, wobei Nicht-ID-Werte in Anführungszeichen eingeschlossen werden, und der Wert kann ein beliebiger Ausdruckstyp sein.

    Eigenschaften sind erforderlich, es sei denn, sie verfügen über einen Optionalitäts-Marker „?“ nach dem Eigenschaftswert. Die -Eigenschaft „sku“ im folgenden Beispiel ist beispielsweise optional:

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

    Decorator-Elemente können für Eigenschaften verwendet werden. * kann verwendet werden, damit alle Werte eine Einschränkung erfordern. Zusätzliche Eigenschaften können weiterhin definiert werden, wenn Sie * verwenden. In diesem Beispiel wird ein Objekt erstellt, für das ein Schlüssel vom Typ intnamens id erforderlich ist, und alle anderen Einträge im Objekt müssen ein Zeichenfolgenwert sein, der mindestens 10 Zeichen lang ist.

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

    Das folgende Beispiel zeigt, wie Sie die Union-Typsyntax verwenden, um einen Satz vordefinierter Werte aufzulisten:

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

    Rekursion

    Objekttypen können eine direkte oder indirekte Rekursion verwenden, solange mindestens ein Zweig des Pfads zum Rekursionspunkt optional ist. Die Definition „myObjectType“ im folgenden Beispiel ist beispielsweise gültig, da die direkt rekursive Eigenschaft „recursiveProp“ optional ist:

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

    Die folgende Typdefinition wäre jedoch ungültig, da level1, level2, level3, level4 oder level5 nicht optional sind.

    type invalidRecursiveObjectType = {
      level1: {
        level2: {
          level3: {
            level4: {
              level5: invalidRecursiveObjectType
            }
          }
        }
      }
    }
    
  • Unäre Bicep-Operatoren können mit ganzzahligen und booleschen Literalen oder Verweisen auf ganzzahlige oder boolesche Literalsymbole verwendet werden:

    type negativeIntLiteral = -10
    type negatedIntReference = -negativeIntLiteral
    
    type negatedBoolLiteral = !true
    type negatedBoolReference = !negatedBoolLiteral
    
  • Unions können eine beliebige Anzahl von Literalausdrücken enthalten. Union-Typen werden in Bicep in die Einschränkung für zulässige Werte übersetzt, sodass nur Literale als Elemente zulässig sind.

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

Zusätzlich zur Verwendung in der Anweisung type können Typausdrücke an diesen Stellen auch zum Erstellen benutzerdefinierter Datentypen verwendet werden:

  • Als Typklausel einer „param“-Anweisung. Beispiel:

    param storageAccountConfig {
      name: string
      sku: string
    }
    
  • Nach „:“ in einer Eigenschaft eines Objekttyps. Beispiel:

    param storageAccountConfig {
     name: string
      properties: {
        sku: string
      }
    } = {
      name: 'store$(uniqueString(resourceGroup().id)))'
      properties: {
        sku: 'Standard_LRS'
      }
    }
    
  • Vor „[]“ in einem Arrayausdruck. Beispiel:

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

Eine typische Bicep-Datei zum Erstellen eines Speicherkontos sieht folgendermaßen aus:

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

Bei Verwendung benutzerdefinierter Datentypen kann sie folgendermaßen aussehen:

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

Verwenden von Decorator-Elementen

Decorator-Elemente werden im Format @expression geschrieben und oberhalb der Deklarationen des benutzerdefinierten Datentyps platziert. In der folgenden Tabelle werden die für benutzerdefinierte Datentypen verfügbaren Decorator-Elemente gezeigt.

Decorator Argument Beschreibung
Beschreibung string Geben Sie Beschreibungen für den benutzerdefinierten Datentyp an.
discriminator Zeichenfolge Verwenden Sie dieses Decorator-Element, um sicherzustellen, dass die richtige Unterklasse identifiziert und verwaltet wird.
Export none Gibt an, dass der benutzerdefinierte Datentyp für den Import durch eine andere Bicep-Datei verfügbar ist.
sealed none Erhöhen Sie BCP089 von einer Warnung auf einen Fehler, wenn ein Eigenschaftenname eines benutzerdefinierten Datentyps wahrscheinlich einen Tippfehler enthält. Weitere Informationen finden Sie unter Erhöhen der Fehlerebene.

Decorators befinden sich im sys-Namespace. Wenn Sie diesen Decorator von einem anderen Element gleichen Namens unterscheiden müssen, stellen Sie dem Decorator sys voran. Wenn Ihre Bicep-Datei z. B. eine Variable mit dem Namen description enthält, müssen Sie den sys-Namespace hinzufügen, wenn Sie den Decorator description verwenden.

Diskriminator

Siehe Markierter Union-Datentyp.

Beschreibung

Fügen Sie dem benutzerdefinierten Datentyp eine Beschreibung hinzu. Decorator-Elemente können für Eigenschaften verwendet werden. Zum Beispiel:

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

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

Mit Markdown formatierter Text kann für den Beschreibungstext verwendet werden.

Exportieren

Verwenden Sie @export(), um den benutzerdefinierten Datentyp für andere Bicep-Dateien freizugeben. Weitere Informationen finden Sie unter Exportieren von Variablen, Typen und Funktionen.

Versiegelt

Siehe Erhöhen der Fehlerebene.

Erhöhen der Fehlerebene

Durch das Deklarieren eines Objekttyps in Bicep können standardmäßig zusätzliche Eigenschaften eines beliebigen Typs akzeptiert werden. Beispielsweise ist der folgende Bicep-Code gültig, löst jedoch die folgende Warnung aus: [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'
}

Die Warnung informiert Sie darüber, dass der anObject-Typ keine Eigenschaft mit dem Namen otionalProperty enthält. Während der Bereitstellung treten zwar keine Fehler auf, weil der Bicep-Compiler davon ausgeht, dass otionalProperty ein Tippfehler ist und dass Sie optionalProperty verwenden wollten, aber die Zeichenfolge falsch geschrieben haben. Er macht Sie daher auf die Inkonsistenz aufmerksam.

Um diese Warnungen auf Fehler heraufzustufen, wenden Sie das Decorator-Element @sealed() auf den Objekttyp an:

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

Sie erhalten die gleichen Ergebnisse, indem Sie das Decorator-Element @sealed() auf die param-Deklaration anwenden:

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

Die ARM-Bereitstellungs-Engine überprüft auch versiegelte Typen auf zusätzliche Eigenschaften. Die Bereitstellung zusätzlicher Eigenschaften für versiegelte Parameter führt zu einem Überprüfungsfehler und dadurch zu einem Fehler bei der Bereitstellung. Zum Beispiel:

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

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

Markierter Union-Datentyp

Um einen benutzerdefinierten markierten Union-Datentyp in einer Bicep-Datei zu deklarieren, können Sie einen discriminator-Decorator über einer benutzerdefinierten Typdeklaration platzieren. Um dieses Decorator-Element nutzen zu können, ist Bicep CLI Version 0.21.X oder höher erforderlich. Das folgende Beispiel zeigt, wie Sie einen markierten Union-Datentyp deklarieren:

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

Weitere Informationen finden Sie unter Benutzerdefinierter markierter Union-Datentyp.

Nächste Schritte

  • Eine Liste der Bicep-Datentypen finden Sie unter Datentypen.