I'm wondering what the proper way to type annotate a return value of a function or method where a class is defined inside of that function.
For example:
from typing import List
from dataclasses import dataclass
def get_users() -> List['ReturnUser']:
@dataclass
class ReturnUser:
first_name: str
last_name: str
return [
ReturnUser("John", "Doe"),
ReturnUser("Jane", "Doe")]
... the ReturnUser dataclass is only relevant within the scope of the function. (I don't care about the object outside of the get_users() function other than that I can access its properties in the calling code).
However, Pylance shows the return value annotation List['ReturnUser'] as a type error. My environment is unfortunately Python 3.7, but also curious about if newer approaches exist in newer Python versions?
How do I annotate a return value that doesn't yet exist like this?
Not only does
ReturnUsernot exist yet, but it's a different class every time. We can verify this easily.So my first advice is to not do this. Make a module-level class and prefix it with an underscore to indicate that it's private. There are very, very, very few good reasons to define a
classinside of adefin Python.That being said, let's suppose this truly is the only way. Let's suppose there's some design constraint not being shown here, and you can't get rid of that class pattern. As I said,
ReturnUseris not a correct return type, since the function returns a value of a different (unrelated) class every time. If you want the return type of your function to be "something with afirst_nameandlast_namefield", we can useProtocolto do that.Now the only type-level guarantee to your callers is that you have properties
first_nameandlast_namewhich are strings. AProtocolis a structural type, which means anything that looks like that class counts as an instance for the purposes of type-checking.