Skip to content

Enhance DX & Type Safety with Typed Loading Methods #109

@ramppdev

Description

@ramppdev

Currently the loading methods (e.g. audobject.from_yaml_s) return an instance of audobject.Object, causing the loss of specific type information for LSPs and tools like mypy.

It might be a good idea to add an optional type parameter (e.g. instance_of) to improve static analysis and type verification.
In addition, this could ensure that the loaded object is actually an instance of the expected type, providing an additional layer of safety and reducing potential runtime errors.

This could default to instance_of=audobject.Object such that full backwards compatibility should be provided (assuming no parameter with the same name was passed).

Example with the loss of typing information:

import audobject


__version__ = "1.0.0"  # pretend we have a package version


class TestObject(audobject.Object):
    def some_method(self, some_arg: str) -> None:
        print(some_arg)


test_object = TestObject()  # test_object is an instance of TestObject
test_object.some_method("hello")  # LSP / mypy information avaliable here

test_yaml = test_object.to_yaml_s()

test_object2 = audobject.from_yaml_s(
    test_yaml
)  # test_object2 is an instance of TestObject but only known as audobject.Object

test_object2.some_method(123)  # no LSP / mypy information available here

Example with added typing information:

from typing import Type, TypeVar


T = TypeVar("T", bound=audobject.Object)


def from_yaml_s_typed(
    yaml_s: str,
    instance_of: Type[T] = audobject.Object,
    **kwargs,
) -> T:
    instance = audobject.from_yaml_s(yaml_s, **kwargs)
    if not isinstance(instance, instance_of):
        raise ValueError(...)
    return instance


test_object3 = from_yaml_s_typed(
    test_yaml,
    instance_of=TestObject,
)  # test_object3 is an instance of TestObject and known as such

test_object3.some_method(123)  # LSP / mypy information available here
# mypy error: Argument 1 to "some_method" of "TestObject" has incompatible type "int"; expected "str"  [arg-type]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions