There is an important principle to consider here:
Even if they are operating at the same nominal voltage you need to worry about connecting one to another if they are operating from separate supplies.
Typically the abs max input voltage limits are Vdd to GND +/- 300mV. When one is off, that means that more than +/-300mV you are violating the absolute maximum spec. If current is not limited, damage can occur, especially when power is re-applied to the one that is off.
There are a few ways to deal with this (in increasing order of cost and performance:
A series resistor (or voltage divider) will limit the current and, if a divider, lower it it a bit.
A BJT or MOSFET can be used with a pullup to the respective supply. BJTs are a bit cheaper and more rugged.
A voltage translator chip with separate supplies (both suppliers go to the chip) can be used. Some chips will accept voltages from 1.8 to 5.5 on either side, or other wide ranges. For example 74AVCH2T45 translates one
bit in each direction from any supply 0.8~3.6 to any supply 0.8~3.6 with propagation times < 10ns in either direction.
To use a resistor, you have to be satisfied with relatively slow propagation delays. For the 3V->3.3V you can almost certainly just use a series resistor. Most 3V-ish devices are CMOS and most are happy with 0.7Vdd or 2.31V for a 3.3V supply, so you would still have 600-700mV of noise margin, which is plenty.
If speed is not an issue, something like 10K is nice, and limits the input current to a really safe level. To go the other way, you might be able to get away with 10K again, but it would be nicer to divide it down by about 10%, so 10K/100K:
simulate this circuit – Schematic created using CircuitLab
Speed wise, if the capacitive load was quite large (say 100pF) due to cable or whatever, then the time constant would be 1us. Probably not a problem for a UART, at least at 115k baud or less.
Of course the transistors invert the signal and the resistors (and most voltage translators) do not, but you knew that.