Skip to content

Self type leads to typing problems #60088

Closed
@julien4215

Description

@julien4215

When trying to define a self type like this class Foo<Self extends Foo<Self>> it is unclear if the methods of the class that return instances of itself should use Self or Foo<Self> as the return type.

  • Using Self as the return type might cause issues when you need to use the type Foo. This will happen when you know only at runtime which subclass of Foo is used.
abstract class Foo<Self extends Foo<Self>> {
  final bool property;

  const Foo(this.property);

  Self copyWith(bool property);

  Self toggle() {
    return copyWith(!property);
  }
}

class Bar extends Foo<Bar> {
  const Bar(super.property);

  @override
  Bar copyWith(bool property) {
    return Bar(property);
  }
}

void main() {
  // Let's pretend that there are multiple subclass of `Foo`
  // and that you know only at runtime which one you will get 
  // so that you need to use the type `Foo`
  Foo someFoo = const Bar(true); // type: Foo<Foo<dynamic>>

  someFoo = someFoo.toggle(); // type: Foo<dynamic>
}

The static analysis fails because when applying the toggle method the type becomes Foo<dynamic> instead of Foo<Foo<dynamic>>.

  • Using Foo<Self> as the return type doesn't mix well with using the name of the subclass as the type. In this example, it would preferable to be able to use the type Bar for the variable someFoo but this is not possible as the toggle method has a return type Foo<Bar>.
abstract class Foo<Self extends Foo<Self>> {
  final bool property;

  const Foo(this.property);

  Foo<Self> copyWith(bool property);

  Foo<Self> toggle() {
    return copyWith(!property);
  }
}

class Bar extends Foo<Bar> {
  const Bar(super.property);

  @override
  Bar copyWith(bool property) {
    return Bar(property);
  }
}

void main() {
  Bar someFoo = const Bar(true); // type: Bar

  someFoo = someFoo.toggle(); // type: Foo<Bar>
}

The static analysis fails because someFoo.toggle() uses the type Foo<Bar> and the variable someFoo is defined with type Bar.


Related to dart-lang/language#3025

Metadata

Metadata

Assignees

No one assigned

    Labels

    closed-as-intendedClosed as the reported issue is expected behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions