You are correct, area emulation just sets the area, while the compiled config for DI is still loaded from the GLOBAL area. If you want to fully leverage di.xml declarations from a different area, you need to use the \Magento\Framework\ObjectManager\ObjectManager::configure method and then use the Object Manager to get the needed classes. For the configure method you will first need to obtain the compiled config for the desired area, using \Magento\Framework\App\ObjectManager\ConfigLoader\Compiled::load. Something like this:
$compiledConfigForFrontendArea = $this->compiledConfigLoader->load(Area::AREA_FRONTEND); $this->state->emulateAreaCode(Area::AREA_FRONTEND, function () use ($compiledConfigForFrontendArea) { //re-configure object manager with grahpql area di compiled config ObjectManager::getInstance()->configure($compiledConfigForFrontendArea); //use the new context to get the class, otherwise di from global area is used and it breaks $desiredObject = ObjectManager::getInstance()->get(DesiredObject::class); }); For my specific use-case (CLI command that needed to run in the GRAPHQL area), I had to use the configure method inside the emulateAreaCode callback. It might work outside of that for your case.
Hope this helps