1

Type hinting method return based on input type

Hi. I'm wondering if it's possible to have intellisense (or whatever it's call in Wing) to understand what a return type will be based on the input to a method. For example:

apple = fruit.to(Apple)
apple.bite() #peel shouldn't be available for code completion, but currently is

orange = fruit.to(Orange)
orange.peel() #Orange shouldn't have bite, but currently does

To_types = typing.Union['Apple','Orange','Fruit', None]

class Fruit():
  @staticmethod
  def can_transform(fruit):
    raise NotImplementedError

  @overload
  def to(self, subclass:'Apple')-> 'Apple':
    ...

  @overload
  def to(self, subclass:'Orange')-> 'Orange':
    ...

  def to(self, subclass:To_types)->To_types:
    result = subclass(self) if subclass.can_transform(self) else None
    return result

class Apple(Fruit):
    @staticmethod
    def can_transform(fruit):
        fruit.is_red()

    def bite(self):
        pass

class Orange(Fruit):
    def peel(self):
        pass

Thanks for any info on this!

nathanieljla's avatar
66
nathanieljla
asked 2025-02-20 17:23:51 -0500
edit flag offensive 0 remove flag close merge delete

Comments

add a comment see more comments

1 Answer

0

As written, obj.to(Apple) doesn't work because def to(self, subclass:'Apple')-> 'Apple': matches when subclass is an instance of Apple not the type object for the Apple class. I suspect you want to use def to(self, subclass: typing.Type['Apple'])-> 'Apple' so that subclass is the type object of the Apple class.

Unfortunately, Wing doesn't not find the right overload if you use subclass: typing.Type['Apple']. This is a bug in Wing and we'll try to fix it soon.

Note that probably a better way to write this is

def to[T: ('Apple', 'Orange')](self, subclass: typing.Type[T]) -> T | None:

This version declares a type parameter that's constrained to Apple or Orange and also specifies that None may be returned. It version uses 3.12+ syntax, but could be written using older syntax. Unfortunately, Wing doesn't determine the correct return type when this version is used; this is also a bug that we'll try to fix.

Wingware Support's avatar
4.2k
Wingware Support
answered 2025-02-21 21:22:45 -0500
edit flag offensive 0 remove flag delete link

Comments

Thanks for the reply. I kept reading up on typing and did eventually land on the code below. It sounds like the overload option is a better choice if you want different return types based on different input types, but in my case it's always going to be a instance of an input class (if a condition is met), so the TypeVar for one method does the trick. I'm glad to hear it's a bug, because I thought I was losing my mind.

import typing

T = typing.TypeVar('T')

class Fruit():
    def to(self, subclass: T) -> T:
        return subclass(self)

class Apple(Fruit):
    def bite(self):
        print('apple bite')

class Orange(Fruit):
    def peel(self):
        print('peel')

fruit = Fruit()

apple = fruit.to(Apple)

apple.bite()

orange = fruit.to(Orange)

orange.peel()
nathanieljla's avatar nathanieljla (2025-02-22 07:45:46 -0500) edit
add a comment see more comments

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account. This space is reserved only for answers. If you would like to engage in a discussion, please instead post a comment under the question or an answer that you would like to discuss.

Add Answer