Multi-Layer Discriminator Hierarchy Building
This document explains how to use the @Azure.ClientGenerator.Core.Legacy.hierarchyBuilding decorator to create multi-layer inheritance hierarchies in discriminated models.
Overview
Section titled “Overview”The @hierarchyBuilding decorator enables client-level multiple levels of inheritance for discriminated models. This decorator modifies the inheritance chain in generated client libraries to create deeper hierarchies than what TypeSpec natively supports.
Use @hierarchyBuilding when you need to represent complex inheritance hierarchies in discriminated models where:
- You have multiple levels of inheritance (grandparent → parent → child)
- You need to share common properties across multiple inheritance levels
- You have explicit permission from SDK architects
Basic Three-Level Hierarchy
Section titled “Basic Three-Level Hierarchy”This example demonstrates a simple three-level inheritance chain: Animal → Pet → Dog.
@discriminator("kind")model Animal { @doc("The kind of animal") kind: string;
@doc("Name of the animal") name: string;}
alias PetContent = { @doc("Whether the pet is trained") trained: boolean;};
model Pet extends Animal { kind: "pet"; ...PetContent;}
alias DogContent = { @doc("The breed of the dog") breed: string;};
@Azure.ClientGenerator.Core.Legacy.hierarchyBuilding(Pet)model Dog extends Animal { kind: "dog"; ...PetContent; ...DogContent;}Without @hierarchyBuilding, Dog would extend Animal directly. With the decorator, Dog extends Pet instead, creating the hierarchy: Animal → Pet → Dog.
from typing import Literalfrom .. import _model_basefrom .._model_base import rest_discriminator, rest_field
class Animal(_model_base.Model): kind: str = rest_discriminator(name="kind") name: str = rest_field()
class Pet(Animal, discriminator="pet"): kind: Literal["pet"] = rest_discriminator(name="kind") trained: bool = rest_field()
class Dog(Pet, discriminator="dog"): # Inherits from Pet, not Animal directly kind: Literal["dog"] = rest_discriminator(name="kind") breed: str = rest_field()//TODOexport interface Pet extends Animal { kind: "pet" | "dog"; /** Whether the pet is trained */ trained: boolean;}
export function petSerializer(item: Pet): any { return { kind: item["kind"], name: item["name"], trained: item["trained"] };}
export function petDeserializer(item: any): Pet { return { kind: item["kind"], name: item["name"], trained: item["trained"], };}
/** Alias for PetUnion */export type PetUnion = Dog | Pet;
export function petUnionSerializer(item: PetUnion): any { switch (item.kind) { default: return petSerializer(item); }}
export function petUnionDeserializer(item: any): PetUnion { switch (item.kind) { case "dog": return dogDeserializer(item as Dog);
default: return petDeserializer(item); }}
/** model interface Dog */export interface Dog extends Pet { kind: "dog"; /** The breed of the dog */ breed: string;}
export function dogDeserializer(item: any): Dog { return { kind: item["kind"], trained: item["trained"], name: item["name"], breed: item["breed"], };}
/** model interface Animal */export interface Animal { /** The kind of animal */ /** The discriminator possible values: pet, dog */ kind: string; /** Name of the animal */ name: string;}
export function animalSerializer(item: Animal): any { return { kind: item["kind"], name: item["name"] };}
export function animalDeserializer(item: any): Animal { return { kind: item["kind"], name: item["name"], };}
/** Alias for AnimalUnion */export type AnimalUnion = PetUnion | Animal;
export function animalUnionSerializer(item: AnimalUnion): any { switch (item.kind) { case "pet": case "dog": return petUnionSerializer(item as PetUnion);
default: return animalSerializer(item); }}
export function animalUnionDeserializer(item: any): AnimalUnion { switch (item.kind) { case "pet": case "dog": return petUnionDeserializer(item as PetUnion);
default: return animalDeserializer(item); }}@Immutablepublic class Animal implements JsonSerializable<Animal> { public String getKind(); public String getName();}
@Immutablepublic class Pet extends Animal { public String getKind(); public boolean isTrained();}
@Immutablepublic final class Dog extends Pet { public String getKind(); public String getBreed();}//TODO