// Utilisation des génériques avec contrainte pour une classe

interface Comparable<T> {
    compare(a:T) : number;
}

class Pile2<T extends NonNullable<Comparable<T>>> {
    valeurs : T[];

    constructor() {
        this.valeurs = [];
    }

    empiler(valeur:T) {
        this.valeurs.push( valeur );
    }

    depiler():T|undefined {
        return this.valeurs.pop();
    }

    max():T|undefined {
        if ( this.valeurs.length == 0 )
            return undefined;
        if ( this.valeurs.length == 1 )
            return this.valeurs[ 0 ];
        let maxVal = this.valeurs[ 0 ];
        for ( let i:number = 1; i < this.valeurs.length; i++ ) {
            let v:T|undefined = this.valeurs[i];
            if ( v!= undefined && maxVal != undefined && v.compare( maxVal ) > 0 )
                maxVal = v;
        }
        return maxVal;
    }
}

class Nombre extends Number implements Comparable<Nombre> {
    compare(a: Nombre): number {
        if ( a.valueOf() > this.valueOf() ) return a.valueOf();
        return this.valueOf();
    }
}

const pileNombre:Pile2<Nombre> = new Pile2<Nombre>();
pileNombre.empiler( new Nombre( 1 ) );
pileNombre.empiler( new Nombre( 2 ) );
console.log( pileNombre.max() );


