-
Notifications
You must be signed in to change notification settings - Fork 754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inheritance for User-Defined Types #14135
Comments
Have also been waiting for this to improve "dirty" UDT's! |
@alex-frankel @stephaniezyen I forgot to ask about it in the Q&A on the community call. What do you guys think about user-defined types inheritance? |
seems like a great addition, but also curious to hear what @stephaniezyen and @jeskew think! |
I think Bicep definitely needs a mechanism for type reuse and composition, but I'm not sure inheritance is the right way to do it. Tagging this for team discussion: some alternatives we can look at would be using intersection ( Some backgroundMy concern is that the Bicep/ARM object model (largely inherited from JSON schema) would allow for declaring child types where an input could validate against the child type but is not guaranteed to validate against the parent. Most object models that are designed to support hierarchies explicitly disallow categories of declarations that are permitted under JSON schema. The best example of this in Bicep's object model is how you would declare a dictionary/map. The Bicep equivalent of type dict = {
*: string
} The equivalent ARM JSON would be as follows, and the same thing in JSON Schema would be very similar: {
...
"definitions": {
"dict": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
} The trouble is introduced by the fact that named properties don't have to validate against the {
"type": "object",
"properties": {
"id": {
"type": "int"
}
},
"additionalProperties": {
"type": "string"
}
} and can be expressed in Bicep as: type aType = {
id: int
*: string
} JSON Schema allows you to declare the same schema using their type composition mechanism ( {
"allOf": [
{
"type": "object",
"properties": {
"id": {
"type": "int"
}
}
},
{
"type": "object",
"unevaluatedProperties": {
"type": "string"
}
}
]
} You can have data that validates against this combined schema ( This situation is OK under the structural type system used by Bicep, ARM, and JSON Schema but would not be under the hierarchical type system users would recognize from any mainstream object-oriented language. Adding type parent = {
*: string
}
type child extends parent = {
id: int
}
var data = {
id: 2
property: 'value'
}
output works child = data // <-- Works! data is a child
output does_not_work parent = data // <-- Throws error! data is not a parent Option 1: Use intersection (
|
+1 on this. It becomes very problematic with discriminator() types. Sometimes the types differ by only 1-2 parameters and if you have 10 types with 10 parameters and 7 of them the same you need to write the same parameters and descriptions 70 times. In case of changes you need to use replace in vscode and be careful that everything is replaced. |
Thanks @jeskew. Had to read into it and I realise there is a lot more to learn on the ARM backend topic 😉. Inheritance doesn't have to be the way to go, it's something I knew from my developer "past". Both options 1 and 2 do what I was aiming for in my inheritance example, but I would vouch for the intersection solution because this is functional wise easy to understand. A large part of the Bicep users do not have a development background (at least the people I work with), so spread can be harder to understand. Also, it looks like option 1 is technically "easier" to implement than option 2? |
I second this. We are trying to implement UDT as a mean of like c# Interfaces. Aka strong typing complex object for your parameters. This will increase the overall resilience of our bicep modules and patterns. The roleAssignmentType is a great example. For every module I would like to have a type that inherits from roleAssignmentType and per module i want to add allowed values for the roleTypeNames. This isn't possible either unfortunately with UDT. Someday i hope the bicep team would look more into c# and see what powerful mechanisms this would offer. You don't have to reinvent the wheel. Its already been done, for decades with c#. Embrace it, it has been build by your colleagues after all. |
Summer is done, checking up on this feature. If we look at MS AVM we see that types are copied everywhere, wich I don't understand, but thats another discussion. I really hope inheritance of user defined types is high on prioty as this will really make bicep more modular and type safe. |
Is your feature request related to a problem? Please describe.
This feature request is not related to a problem I have, but more like an improvement on User-Defined Types (UDT). I am looking at UDTs like a class in TypeScript or C# for example. I know it's a different concept in Bicep, but it looks similar.
What would be great is to have the same concept of class inheritance in User-Defined Types. So, to have some kind of
base
type where other UDTs canextend
orinherit
from that base type.Describe the solution you'd like
A clear and concise description of what you want to happen.
I will provide a practical example. In my recent PR in the Azure Verified Modules (Azure/bicep-registry-modules#1931) repository I tried to achieve some kind of "inheritance" this way:
In the
zoneBaseType
UDT the base properties are defined that are used in every record type (a, aaaa, cname etc.) as seen below:The outcome is what I wanted, but not quite what I had in mind.
What would be great functionality to have is inheritance like we see in C# and TypeScript, so we can remove the need for a property like the
base: zoneBaseType
property.How I see it with inheritance:
The type
aType
now extends frombaseType
, so when using the UDTaType
you make use of the following properties:I hope this is clear and understandable. If not, please let me know.
The text was updated successfully, but these errors were encountered: