Benutzerdefinierte Datentypen in Bicep

Erfahren Sie, wie Sie benutzerdefinierte Datentypen in Bicep verwenden.

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

Syntax für benutzerdefinierte Datentypen

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

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

Hinweis

Das @allowed-Decorator-Element ist nur für param-Anweisungen zulässig. Um zu deklarieren, dass eine Eigenschaft einer Gruppe vordefinierter Werte in einer type- oder output-Anweisung angehören muss, verwenden Sie die Union-Typsyntax. Die Union-Typsyntax kann auch in param-Anweisungen verwendet werden.

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. 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
    
  • Arraytypen können durch das Suffix „[]“ für einen beliebigen gültigen Typausdruck deklariert werden:

    // 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. Der Schlüssel und der Wert werden durch einen Doppelpunkt (:) getrennt. Der Schlüssel kann eine beliebige Zeichenfolge sein (Werte, die kein gültiger Bezeichner wären, müssen in Anführungszeichen eingeschlossen werden), der Wert ein beliebiger Typsyntaxausdruck.

    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 int namens id erforderlich ist, und alle anderen Einträge im Objekt müssen aus einer Zeichenfolge bestehen, die 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 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@2022-09-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@2022-09-01' = {
  name: storageAccountConfig.name
  location: location
  sku: {
    name: storageAccountConfig.sku
  }
  kind: 'StorageV2'
}

Deklarieren des markierten Union-Typs

Um einen benutzerdefinierten Union-Datentyp in einer Bicep-Datei zu deklarieren, können Sie ein Decorator-Element für den Diskriminator über einer benutzerdefinierten Typdeklaration platzieren. Um dieses Decorator-Element nutzen zu können, ist Bicep CLI Version 0.21.X oder höher erforderlich. Die Syntax lautet:

@discriminator('<propertyName>')

Das Decorator-Element für den Diskriminator akzeptiert einen einzelnen Parameter, der einen freigegebenen Eigenschaftsnamen zwischen allen Union-Membern darstellt. Bei diesem Eigenschaftsnamen muss es sich um ein erforderliches Zeichenfolgenliteral für alle Member handeln, wobei die Groß-/Kleinschreibung beachtet wird. Die Werte der unterscheidenden Eigenschaft für die Union-Member müssen eindeutig sein, wobei die Groß-/Kleinschreibung nicht beachtet werden muss.

Das folgende Beispiel zeigt, wie Sie einen markierten Union-Typ 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

Der Parameterwert wird basierend auf dem unterscheidenden Eigenschaftswert überprüft. Wenn der Wert des Parameters ServiceConfig im vorstehenden Beispiel vom Typ foo ist, wird er unter Verwendung des Typs FooConfig überprüft. Analog gilt, wenn der Parameterwert vom Typ bar ist, wird die Überprüfung mit dem Typ BarConfig durchgeführt, und dieses Muster setzt sich auch bei den anderen Typen fort.

Importieren von Typen zwischen Bicep-Dateien (Vorschau)

Um diese Kompilierzeit-Importfunktion nutzen zu können, wird Bicep CLI Version 0.21.X oder höher benötigt. Das experimentelle Flag compileTimeImports muss über die Bicep-Konfigurationsdatei aktiviert werden.

Nur benutzerdefinierte Datentypen, die den @export()-Decorator aufweisen, können in andere Vorlagen importiert werden. Derzeit kann dieser Decorator nur für type-Anweisungen verwendet werden.

Mit dem folgenden Beispiel können Sie die zwei benutzerdefinierten Datentypen aus anderen Vorlagen importieren:

@export()
type myStringType = string

@export()
type myOtherStringType = myStringType

Weitere Informationen finden Sie unter Importieren benutzerdefinierter Datentypen.

Nächste Schritte

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