As @InSync mentioned in the comments we can solve this by adding a third overload.
from __future__ import annotations
from typing import Literal, overload
class WoodData: ...
class ConcreteData: ...
class Foo[T: Literal["wood", "concrete"]]:
def __init__(self, data_type: T) -> None:
self.data_type = data_type
@overload
def get_data(self: Foo[Literal["wood"]]) -> WoodData: ...
@overload
def get_data(self: Foo[Literal["concrete"]]) -> ConcreteData: ...
@overload
def get_data(self) -> WooData | ConcreteData: ...
def get_data(self):
if self.data_type == "wood":
return WoodData()
return ConcreteData()
def bar(self):
self.get_data()