OK so, this is actually the "type" within a CAST so this is not something that gets "bound" into a SQL query, "bound parameters" are only used for data values, not syntactical elements of a query as a type would be.
what's not clear here is when it is that you know what this type would be. do you know what the type would be before you invoke the query, or is the type a product of something in the data that's being read? if the latter case, you'd need to use a CASE so that the determination is made within the SQL process.
otherwise the easiest way to do this is to just parameterize your bake_extract_settings_query() function to return different select() structures with the different type inside the CAST.
The other two ways to make the statement change per execution is as you noted the @compiles version, and then you could also use visit replacement in conjunction with the before_execute event. The latter approach might work better in that you don't need to worry that the SQL was cached since you will be intercepting it each time, and you also get to work upon the whole statement at once. Yet another way would be to process the string SQL directly using the before_cursor_execute() event.
the challenge with all of those is knowing what type you want to use each time as it's not clear what mechanism you are using in order to know this. if some part of your program wants to say, "execute_query(desired_type=String)" then you have to get that "desired_type" somewhere that an event hook can get it, like in a threading.local() or somehow carried along with the compiler or the connection. But if you're doing that I don't see why you wouldn't just send that type to bake_extract_settings_query() and make a new select().
so short answer yes there are ways to change the inside of the statement each time but those are inside of event hooks where you'd need to invent some way of passing the desired value inside, and it's not clear why you need to do that rather than just call bake_extract_settings_query() again. If there are say five different datatypes you could always just put five select() structures in a dictionary if you are trying to avoid calling select() many times. (is the issue performance? there's a lot to say about that if so)