Partage via


Types de données définis par l’utilisateur dans Bicep

Découvrez comment créer des types de données définis par l’utilisateur(-trice) dans Bicep. Pour connaître les types de données définis par le système, consultez Types de données.

Bicep CLI version 0.12.X ou ultérieure est nécessaire pour utiliser cette fonctionnalité.

Définir des types

Vous pouvez employer l’instruction type pour définir les types de données définis par l’utilisateur(-trice). Vous pouvez également utiliser des expressions type à certains endroits pour définir des types personnalisés.

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

Le décorateur @allowed n’est autorisé que sur les instructions param. Pour déclarer un type avec un ensemble de valeurs prédéfinies dans une type, utilisez la syntaxe de type union.

Les expressions type valides sont les suivantes :

  • Les références symboliques sont des identificateurs qui font référence à un type ambiant (comme string ou int) ou à un symbole type défini par l’utilisateur déclaré dans une instruction type :

    // Bicep data type reference
    type myStringType = string
    
    // user-defined type reference
    type myOtherStringType = myStringType
    
  • Les littéraux primitifs, dont les chaînes, les entiers et les booléens, sont des expressions type valides. Par exemple :

    // 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
    
  • Vous pouvez déclarer des types de tableaux en ajoutant [] à n’importe quelle expression de type valide :

    // 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)[]
    
  • Les types d’objets contiennent zéro ou plusieurs propriétés entre crochets bouclés :

    type storageAccountConfigType = {
      name: string
      sku: string
    }
    

    Chaque propriété d’un objet se compose d’une clé et d’une valeur, séparées par un signe deux-points :. La clé peut être n’importe quelle chaîne, les valeurs non identifiantes étant placées entre guillemets, et la valeur peut être n’importe quel type d’expression.

    Les propriétés sont requises, sauf si elles ont un marqueur d'option ? après la valeur de propriété. Par exemple, la propriété sku dans l’exemple suivant est facultative :

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

    Des éléments décoratifs peuvent être utilisés sur les propriétés. * peut être utilisé pour que toutes les valeurs nécessitent une contrainte. Des propriétés supplémentaires peuvent toujours être définies lors de l’utilisation de *. Cet exemple crée un objet dont la clé doit être de type int nommée id, et dont toutes les autres entrées doivent être des chaînes de caractères d’au moins 10 caractères.

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

    L’exemple suivant montre comment utiliser la syntaxe de type union pour répertorier un ensemble de valeurs prédéfinies :

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

    Récursivité

    Les types d’objets peuvent utiliser une récursivité directe ou indirecte, tant qu’au moins la partie du chemin d’accès au point de récursivité est facultative. Par exemple, la définition myObjectType dans l’exemple suivant est valide, car la propriété directement récursive recursiveProp est facultative :

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

    Mais la définition de type suivante n’est pas valide, car aucune de level1, level2, , level3 level4ou level5 n’est facultative.

    type invalidRecursiveObjectType = {
      level1: {
        level2: {
          level3: {
            level4: {
              level5: invalidRecursiveObjectType
            }
          }
        }
      }
    }
    
  • Les opérateurs unaires Bicep peuvent être employés avec des littéraux entiers et booléens ou des références à des symboles entiers ou de type littéral booléen :

    type negativeIntLiteral = -10
    type negatedIntReference = -negativeIntLiteral
    
    type negatedBoolLiteral = !true
    type negatedBoolReference = !negatedBoolLiteral
    
  • Les unions peuvent comporter n’importe quel nombre d’expressions type littérales. Les types union étant traduits en contrainte de valeur autorisée dans Bicep, seuls les littéraux sont autorisés comme membres.

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

En plus d’être utilisées dans l’instruction type, les expressions de type peuvent également être utilisées à ces emplacements pour créer des types de dates définis par l’utilisateur :

  • Comme clause type d’une param instruction. Par exemple :

    param storageAccountConfig {
      name: string
      sku: string
    }
    
  • Suivant le : dans une propriété type d’objet. Par exemple :

    param storageAccountConfig {
     name: string
      properties: {
        sku: string
      }
    } = {
      name: 'store$(uniqueString(resourceGroup().id)))'
      properties: {
        sku: 'Standard_LRS'
      }
    }
    
  • Précédant le [] dans une expression type tableau. Par exemple :

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

Un fichier Bicep classique pour la création d’un compte de stockage ressemble à ceci :

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

En employant des types de données définis par l’utilisateur, il peut se présenter comme suit :

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

Utiliser des éléments décoratifs

Les éléments décoratifs sont écrits au format @expression et sont placés au-dessus des déclarations du type de données défini par l’utilisateur. Le tableau suivant présente les éléments décoratifs disponibles pour les types de données définis par l’utilisateur.

Élément décoratif S’applique à Argument Description
description all string Fournissez des descriptions pour le type de données défini par l’utilisateur.
discriminator object string Utilisez cet élément décoratif pour vous assurer que la sous-classe appropriée est identifiée et gérée.
export all Aucune Indique que le type de données défini par l’utilisateur est disponible pour l’importation par un autre fichier Bicep.
maxLength array, string int La longueur maximale pour les types de données de chaîne et de tableau. La valeur est inclusive.
maxValue int int La valeur maximale pour les types de données entiers. Cette valeur est inclusive.
métadonnées all object La propriétés personnalisées à appliquer aux types de données. Peut inclure une propriété Description qui est équivalente à l’élément décoratif de description.
minLength array, string int La longueur minimale pour les types de données de chaîne et de tableau. La valeur est inclusive.
minValue int int La valeur minimale pour les types de données entiers. Cette valeur est inclusive.
sealed object Aucune Élever BCP089 d’avertissement à erreur lorsqu’un nom de propriété d’un type de données défini par l’utilisateur est probablement une faute de frappe. Pour plus d’informations, consultez Élever le niveau d’erreur.
secure string, object Aucune Marque les types comme sécurisés. La valeur d’un type sécurisé n’est pas enregistrée dans l’historique de déploiement et n’est pas journalisée. Pour plus d’informations, consultez Sécuriser les chaînes et les objets.

Les éléments décoratifs se trouvent dans l’espace de noms sys. Si vous devez différencier un élément décoratif d'un autre élément portant le même nom, faites précéder l’élément décoratif de sys. Par exemple, si votre fichier Bicep contient une variable nommée description, vous devez ajouter l’espace de noms sys lors de l’utilisation de l’élément décoratif description.

Discriminant

Consultez Type de données d’union étiquetée.

Description

Ajoutez une description au type de données défini par l’utilisateur. Des éléments décoratifs peuvent être utilisés sur les propriétés. Par exemple :

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

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

Du texte au format Markdown peut être utilisé pour le texte de description.

Export

Utilisez @export() pour partager le type de données défini par l’utilisateur avec d’autres fichiers Bicep. Pour plus d’informations, consultez Exporter des variables, des types et des fonctions.

Contraintes d’entier

Vous pouvez définir des valeurs minimales et maximales pour le type entier. Vous pouvez définir une contrainte ou les deux.

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

Contraintes de longueur

Vous pouvez spécifier des longueurs minimale et maximale pour les types de chaîne et de tableau. Vous pouvez définir une contrainte ou les deux. Pour les chaînes, la longueur indique le nombre de caractères. Pour les tableaux, la longueur indique le nombre d’éléments dans le tableau.

L’exemple suivant déclare deux types. Un type est destiné à un nom de compte de stockage qui doit compter entre 3 et 24 caractères. L’autre type est un tableau qui doit compter entre 1 et 5 éléments.

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

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

Métadonnées

Si vous avez des propriétés personnalisées que vous souhaitez appliquer à un type de données défini par l’utilisateur, ajoutez un élément décoratif de métadonnées. Dans les métadonnées, définissez un objet avec des noms et valeurs personnalisés. L’objet que vous définissez pour les métadonnées peut contenir des propriétés de n’importe quel nom et type.

Vous pouvez utiliser cet élément décoratif pour suivre les informations relatives au type de données qu’il n’est pas utile d’ajouter à la description.

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

Lorsque vous fournissez un @metadata() élément décoratif avec une propriété qui est en conflit avec un autre élément décoratif, cet élément décoratif est toujours prioritaire sur tout ce qui se passe dans @metadata() l’élément décoratif. Par conséquent, la propriété en conflit dans la valeur @metadata() est redondante et sera remplacée. Pour plus d’informations, consultez Aucune métadonnée en conflit.

Scellé

Consultez Élever le niveau d’erreur.

Types sécurisés

Vous pouvez marquer le type de données défini par l’utilisateur comme étant sécurisé. La valeur d’un type sécurisé n’est pas enregistrée dans l’historique de déploiement et n’est pas journalisée.

@secure()
type demoPassword string

@secure()
type demoSecretObject object

Élever le niveau d’erreur

Par défaut, la déclaration d’un type d’objet dans Bicep lui permet d’accepter des propriétés supplémentaires de n’importe quel type. Par exemple, le bicep suivant est valide, mais déclenche un avertissement de [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’avertissement vous informe que le type anObject n’inclut pas de propriété nommée otionalProperty. Bien qu’aucune erreur ne se produise pendant le déploiement, le compilateur Bicep suppose optionalProperty est une faute de frappe, que vous avez l’intention d’utiliser optionalProperty, mais l’a mal orthographié, et de vous avertir de l’incohérence.

Pour réaffecter ces avertissements aux erreurs, appliquez le décorateur @sealed() au type d’objet :

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

Vous obtenez les mêmes résultats en appliquant le décorateur @sealed() à la déclaration param :

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

Le moteur de déploiement ARM vérifie également les types scellés pour obtenir des propriétés supplémentaires. La fourniture de toutes les propriétés supplémentaires pour les paramètres scellés entraîne une erreur de validation, ce qui entraîne l’échec du déploiement. Par exemple :

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

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

Type de données union étiqueté

Pour déclarer un type de données d’union étiqueté personnalisé dans un fichier Bicep, vous pouvez placer un élément décoratif discriminator au-dessus d’une déclaration de type défini par l’utilisateur. Bicep CLI version 0.21.X ou ultérieure est nécessaire pour utiliser cet élément décoratif. L’exemple suivant montre comment déclarer un type de données union étiqueté :

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

Pour plus d’informations, consultez Type de données union étiqueté personnalisé.

Étapes suivantes