Typy danych zdefiniowane przez użytkownika w Bicep

Dowiedz się, jak używać typów danych zdefiniowanych przez użytkownika w aplikacji Bicep.

Do korzystania z tej funkcji jest wymagany interfejs wiersza polecenia Bicep w wersji 0.12.X lub nowszej .

Składnia typu danych zdefiniowanego przez użytkownika

Instrukcję type można użyć do zdefiniowania typów danych zdefiniowanych przez użytkownika. Ponadto można również użyć wyrażeń typu w niektórych miejscach do definiowania typów niestandardowych.

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

Uwaga

Dekorator @allowed jest dozwolony tylko naparaminstrukcjach. Aby zadeklarować, że właściwość musi być jednym z zestawu wstępnie zdefiniowanych wartości w type instrukcji lub output , użyj składni typu unii. Składnia typu unii może być również używana w param instrukcjach.

Prawidłowe wyrażenia typów obejmują:

  • Odwołania symboliczne to identyfikatory odwołujące się do typu otoczenia (na przykład string lub int) lub symbolu typu zdefiniowanego przez użytkownika zadeklarowanego w instrukcji type :

    // Bicep data type reference
    type myStringType = string
    
    // user-defined type reference
    type myOtherStringType = myStringType
    
  • Literały pierwotne, w tym ciągi, liczby całkowite i wartości logiczne, są prawidłowymi wyrażeniami typów. Na przykład:

    // 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
    
  • Typy tablic można zadeklarować przez sufiks do [] dowolnego prawidłowego wyrażenia typu:

    // 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)[]
    
  • Typy obiektów zawierają zero lub więcej właściwości między nawiasami klamrowymi:

    type storageAccountConfigType = {
      name: string
      sku: string
    }
    

    Każda właściwość w obiekcie składa się z klucza i wartości. Klucz i wartość są oddzielone dwukropkiem :. Klucz może być dowolnym ciągiem (wartości, które nie byłyby prawidłowym identyfikatorem, muszą być ujęte w cudzysłowy), a wartość może być dowolnym wyrażeniem składni typu.

    Właściwości są wymagane, chyba że mają znacznik ? opcjonalności po wartości właściwości. Na przykład właściwość w poniższym przykładzie sku jest opcjonalna:

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

    Dekoratory mogą być używane we właściwościach. * Może służyć do określania, że wszystkie wartości wymagają ograniczenia. Dodatkowe właściwości mogą być nadal definiowane w przypadku używania polecenia *. W tym przykładzie tworzony jest obiekt, który wymaga klucza typu int o nazwie idi że wszystkie inne wpisy w obiekcie muszą być wartością ciągu co najmniej 10 znaków.

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

    W poniższym przykładzie pokazano, jak używać składni typu unii do wyświetlania listy wstępnie zdefiniowanych wartości:

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

    Rekursja

    Typy obiektów mogą używać rekursji bezpośredniej lub pośredniej, o ile co najmniej część ścieżki do punktu rekursji jest opcjonalna. Na przykład definicja w poniższym przykładzie jest prawidłowa, myObjectType ponieważ właściwość bezpośrednia rekursywna recursiveProp jest opcjonalna:

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

    Jednak następująca definicja typu nie byłaby prawidłowa, ponieważ żadna z wartości level1, level2, level3, level4lub level5 nie jest opcjonalna.

    type invalidRecursiveObjectType = {
      level1: {
        level2: {
          level3: {
            level4: {
              level5: invalidRecursiveObjectType
            }
          }
        }
      }
    }
    
  • Operatory jednoargumentowe Bicep mogą być używane z literałami całkowitymi i logicznymi lub odwołaniami do symboli typu całkowitoliczbowego lub logicznego:

    type negativeIntLiteral = -10
    type negatedIntReference = -negativeIntLiteral
    
    type negatedBoolLiteral = !true
    type negatedBoolReference = !negatedBoolLiteral
    
  • Związki mogą zawierać dowolną liczbę wyrażeń typowych literałów. Typy unii są tłumaczone na ograniczenie dozwolonej wartości w Bicep, więc tylko literały są dozwolone jako elementy członkowskie.

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

Oprócz użycia w instrukcji type wyrażenia typu można również używać w tych miejscach do tworzenia typów danych zdefiniowanych przez użytkownika:

  • Jako klauzula param type instrukcji. Na przykład:

    param storageAccountConfig {
      name: string
      sku: string
    }
    
  • : Po właściwości w typie obiektu. Na przykład:

    param storageAccountConfig {
     name: string
      properties: {
        sku: string
      }
    } = {
      name: 'store$(uniqueString(resourceGroup().id)))'
      properties: {
        sku: 'Standard_LRS'
      }
    }
    
  • Poprzedzając element [] w wyrażeniu typu tablicy. Na przykład:

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

Typowy plik Bicep do utworzenia konta magazynu wygląda następująco:

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

Korzystając z typów danych zdefiniowanych przez użytkownika, może to wyglądać następująco:

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

Deklarowanie oznakowanego typu unii

Aby zadeklarować niestandardowy otagowany typ danych unii w pliku Bicep, można umieścić dyskryminujący dekorator powyżej deklaracji typu zdefiniowanego przez użytkownika. Do korzystania z tego dekoratora wymagany jest interfejs wiersza polecenia Bicep w wersji 0.21.X lub nowszej . Składnia jest następująca:

@discriminator('<propertyName>')

Dekorator dyskryminujący przyjmuje jeden parametr, który reprezentuje nazwę właściwości udostępnionej wśród wszystkich składowych unii. Ta nazwa właściwości musi być wymaganym literałem ciągu dla wszystkich elementów członkowskich i uwzględnia wielkość liter. Wartości dyskryminowanej własności członków związku muszą być unikatowe w sposób niewrażliwy na wielkość liter.

W poniższym przykładzie pokazano, jak zadeklarować otagowany typ unii:

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

Wartość parametru jest weryfikowana na podstawie wartości właściwości dyskryminowanej. W poprzednim przykładzie, jeśli wartość parametru serviceConfig jest typu foo, przechodzi walidację przy użyciu typu FooConfig. Podobnie, jeśli wartość parametru jest paskiem typu, walidacja jest wykonywana przy użyciu typu BarConfig, a ten wzorzec również będzie kontynuowany dla innych typów.

Importowanie typów między plikami Bicep (wersja zapoznawcza)

Do korzystania z tej funkcji importowania w czasie kompilacji wymagany jest interfejs wiersza polecenia Bicep w wersji 0.21.X lub nowszej . Flaga compileTimeImports eksperymentalna musi być włączona z pliku konfiguracji Bicep.

Do innych szablonów można zaimportować tylko typy danych zdefiniowane przez użytkownika, które mają @export() dekorator. Obecnie ten dekorator może być używany tylko w type instrukcjach.

Poniższy przykład umożliwia importowanie dwóch typów danych zdefiniowanych przez użytkownika z innych szablonów:

@export()
type myStringType = string

@export()
type myOtherStringType = myStringType

Aby uzyskać więcej informacji, zobacz Importowanie typów danych zdefiniowanych przez użytkownika.

Następne kroki

  • Aby uzyskać listę typów danych Bicep, zobacz Typy danych.