Skip to content

Allow derived csp.Struct classes to override base class types if new types are more specialized #517

@p72dennisxu

Description

@p72dennisxu

Is your feature request related to a problem? Please describe.
Currently a derived csp.Struct class is not able to override the types of fields defined in the base class, which leads to incorrect types when the derived struct actually expects a more specialized type for the field. For example, suppose that we have the following structs for storing some data

class Base(csp.Struct):
    x: int

class Derived(Base):
    y: str

and the following structs

class Test1(csp.Struct):
    info: str
    data: Base

class Test2(Test1):
    more_info: list

where we in addition expect that Test2's data field should now have the type Derived. We can set the field to some instance of Derived since it's a subtype of Base, but setting it to Base will not result in any type errors, leading to potential runtime crashes and incompatibility with from_dict.

Describe the solution you'd like
One possible solution is to allow overriding only when the new type is a subtype of the base class type. This is consistent with the type systems in some other languages, ex. TypeScript:

interface Base {
    x: number;
}
interface Derived extends Base {
    y: string;
}
interface Test1 {
    data: Base;
}
interface Test2 extends Test1 {
    data: Derived;
}
function test1(obj: Derived) {
    const x: Test1 = {
        data: obj
    }
    console.log(x);
}
function test2(obj: Base) {
    const x: Test2 = {
        data: obj
    }
    console.log(x);
}
const baseObj: Base = {
    x: 1
}
const derivedObj: Derived = {
    x: 1,
    y: '2'
}
test1(derivedObj);
test2(baseObj);

In this case, we can set field data of Test1 to some instance of Derived but not the same field on Test2 to some instance of Base.

Describe alternatives you've considered
With the current setup, we need to copy all the other fields from the base class to ensure that we have the correct types, i.e.

class Test2(csp.Struct):
    info: str
    data: Derived
    more_info: list

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: enhancementIssues and PRs related to improvements to existing features

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions