What is an elegant way to catch multiple exceptions without catching generic exceptions?

You can still support concrete types with getTypeName by using the Type.forName method.

Set<Type> whilelist = new Set<Type> { DmlException.class, ListException.class };
try
{
    // do stuff
}
catch (Exception pokemon)
{
    if (!whitelist.contains(Type.forName(pokemon.getTypeName()))
    {
        throw pokemon;
    }
    // actual error handling logic here
}

It's doable with an abstract base class as shown below.

public abstract class CustomException extends System.Exception {

}

Implementing exception classes

public class AException extends CustomException {

}


public class BException extends CustomException {

}

This test proves that it works

@IsTest
private class CustomException_Test {

    @IsTest
    private static void genericHandling() {

        Boolean aCatched = false;
        Boolean bCatched = false;
        Boolean othersIgnored = true;

        try {
            throw new AException();
        }
        catch(CustomException cex) {
            aCatched = true;
        }

        try {
            throw new BException();
        }
        catch(CustomException cex) {
            bCatched = true;
        }

        try {
            throw new NotACustomException();
        }
        catch(CustomException cex) {
            othersIgnored = false;
        }
        catch(Exception ex) {
            othersIgnored = true;
        }

        System.assert(aCatched);
        System.assert(bCatched);
        System.assert(othersIgnored);
    }
}