Partekatu honen bidez:


Tipos de datos definidos por el usuario en Bicep

Aprende a crear tipos de datos definidos por el usuario en Bicep. Para los tipos de datos definidos por el sistema, consulte Tipos de datos.

Para usar esta característica se necesita la versión 0.12.X o posterior de la CLI de Bicep.

Definición de tipos

Puede usar la instrucción type para crear tipos de datos definidos por el usuario. Además, también puedes usar expresiones de tipo en algunos lugares para definir tipos personalizados.

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

El decorador @allowed solo se permite enparam instrucciones. Para declarar un tipo con un conjunto de valores predefinidos en un type, use sintaxis de tipo de unión.

Las expresiones de tipo válidas incluyen:

  • Las referencias simbólicas son identificadores que hacen referencia a un tipo ambiente (como string o int) o a un símbolo de tipo definido por el usuario declarado en una instrucción type:

    // Bicep data type reference
    type myStringType = string
    
    // user-defined type reference
    type myOtherStringType = myStringType
    
  • Los literales primitivos, incluidas las cadenas, los enteros y los booleanos, son expresiones de tipo válidas. Por ejemplo:

    // 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
    
  • Puede declarar tipos de matriz anexando [] a cualquier expresión de tipo válida:

    // 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)[]
    
  • Los tipos de objeto contienen cero o más propiedades entre corchetes:

    type storageAccountConfigType = {
      name: string
      sku: string
    }
    

    Cada propiedad de un objeto consta de una clave y un valor, separados por dos puntos :. La clave puede ser cualquier cadena, con los valores no identificadores entre comillas, y el valor puede ser cualquier tipo de expresión.

    Las propiedades son necesarias a menos que tengan un marcador de opcionalidad ? después del nombre de propiedad y los dos puntos. Por ejemplo, la propiedad sku del ejemplo siguiente es opcional:

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

    Los decoradores se pueden usar en propiedades. * puede utilizarse para que todos los valores requieran una restricción. Es posible que todavía se definan propiedades adicionales al usar *. En este ejemplo se crea un objeto que requiere una clave de tipo int denominada id y que todas las demás entradas del objeto deben ser un valor de cadena de al menos 10 caracteres.

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

    En el ejemplo siguiente se muestra cómo usar la sintaxis de tipo de unión para enumerar un conjunto de valores predefinidos:

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

    Recursividad

    Los tipos de objeto pueden usar recursividad directa o indirecta, siempre y cuando al menos la pierna de la ruta de acceso al punto de recursividad sea opcional. Por ejemplo, la definición myObjectType del ejemplo siguiente es válida porque la propiedad directamente recursiva recursiveProp es opcional:

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

    Pero la siguiente definición de tipo no sería válida porque ninguna de level1, level2, level3, level4 o level5 es opcional.

    type invalidRecursiveObjectType = {
      level1: {
        level2: {
          level3: {
            level4: {
              level5: invalidRecursiveObjectType
            }
          }
        }
      }
    }
    
  • Los operadores unarios de Bicep se pueden usar con literales enteros y booleanos o referencias a símbolos de tipo literal booleano o entero:

    type negativeIntLiteral = -10
    type negatedIntReference = -negativeIntLiteral
    
    type negatedBoolLiteral = !true
    type negatedBoolReference = !negatedBoolLiteral
    
  • Las uniones pueden incluir cualquier número de expresiones con tipo literal. Los tipos de unión se traducen en la restricción de valor permitido en Bicep, por lo que solo se permiten literales como miembros.

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

Además de usarse en la instrucción type, las expresiones de tipo también se pueden usar en estos lugares para crear tipos de datos definidos por el usuario:

  • Como la cláusula tipo de una instrucción param. Por ejemplo:

    param storageAccountConfig {
      name: string
      sku: string
    }
    
  • Después de : en una propiedad de tipo de objeto. Por ejemplo:

    param storageAccountConfig {
     name: string
      properties: {
        sku: string
      }
    } = {
      name: 'store$(uniqueString(resourceGroup().id)))'
      properties: {
        sku: 'Standard_LRS'
      }
    }
    
  • Anterior a [] en una expresión de tipo de matriz. Por ejemplo:

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

Un archivo de Bicep típico para crear una cuenta de almacenamiento tiene el siguiente aspecto:

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

Mediante el uso de tipos de datos definidos por el usuario, puede tener el siguiente aspecto:

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

Uso de decoradores

Los decoradores se escriben en el formato @expression y se colocan encima de las declaraciones del tipo de datos definido por el usuario. En la tabla siguiente se muestran los decoradores disponibles para los tipos de datos definidos por el usuario.

Decorador Argumento Descripción
descripción string Proporcione descripciones para el tipo de datos definido por el usuario.
discriminator string Use este decorador para asegurarse de que la subclase correcta se identifica y administra.
export None Indica que el tipo de datos definido por el usuario está disponible para la importación por otro archivo de Bicep.
sealed None Eleve BCP089 de una advertencia a un error cuando es probable que un nombre de propiedad de un tipo de datos use-define sea un error tipográfico. Para obtener más información, consulte Elevación del nivel de error.

Los decoradores están en el espacio de nombres sys. Si tiene que diferenciar un decorador de otro elemento con el mismo nombre, anteceda el decorador con sys. Por ejemplo, si el archivo de Bicep incluye una variable llamada description, debe agregar el espacio de nombres sys al usar el decorador description.

Discriminador

Consulte Tipo de datos de unión etiquetado.

Descripción

Agregue una descripción al tipo de datos definido por el usuario. Los decoradores se pueden usar en propiedades. Por ejemplo:

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

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

El texto con formato Markdown se puede usar para el texto de descripción.

Exportación

Use @export() para compartir el tipo de datos definido por el usuario con otros archivos de Bicep. Para más información, consulte Exportación de variables, tipos y funciones.

Sellado

Consulte Elevación del nivel de error.

Elevar nivel de error

De forma predeterminada, declarar un tipo de objeto en Bicep permite aceptar propiedades adicionales de cualquier tipo. Por ejemplo, el Bicep siguiente es válido, pero genera una advertencia 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'
}

La advertencia le informa de que el tipo anObject no incluye una propiedad denominada otionalProperty. Aunque no se producen errores durante la implementación, el compilador de Bicep supone que otionalProperty es un error tipográfico, que pretende usar opcionalProperty pero lo ha escrito mal y le avisará de la incoherencia.

Para escalar estas advertencias a errores, aplique el decorador @sealed() al tipo de objeto:

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

Para obtener los mismos resultados, aplique el decorador @sealed() a la declaración param:

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

El motor de implementación de ARM también comprueba los tipos sellados para propiedades adicionales. Si se proporcionan propiedades adicionales para los parámetros sellados, se produce un error de validación, lo que provoca un error en la implementación. Por ejemplo:

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

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

Tipo de datos de unión etiquetado

Para declarar un tipo de datos de unión etiquetado personalizado dentro de un archivo de Bicep, puede colocar un decorador discriminator encima de una declaración de tipo definida por el usuario. Para usar este decorador se necesita la versión 0.21.X o posterior de la CLI de Bicep. En el ejemplo siguiente se muestra cómo declarar un tipo de datos de unión etiquetado:

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

Para obtener más información, vea Tipo de datos de unión etiquetado personalizado.

Pasos siguientes

  • Para obtener una lista de los tipos de datos de Bicep, consulte Tipos de datos.