Home > Net >  Type inference is dynamic on operator overloading with extension in Dart
Type inference is dynamic on operator overloading with extension in Dart

Time:06-25

I try to implement pipe-operator overriding |

extension Pipe on Object {
  operator |(Function(Object) f) => f(this);
}

typedef Id = A Function<A>(A);
Id id = <A>(A a) => a;

var t1 = id("test");  // String t1
var t2 = "test" | id; // dynamic t2

with the generic Id function above, on id("test") is detected as String, but "test" | id is dynamic which is very problematic.

How can I fix this?


EDIT

Thankfully, @jamesdlin has answered and suggested:

extension Pipe on Object {
  Object operator |(Object Function(Object) f) => f(this);
}

the result has improved as

var t2 = "test" | id; // Object t2

I also tried with generic as follows:

extension Pipe<A, B> on A {
  B operator |(B Function(A) f) => f(this);
}

I expected it would go better because I thought the generic A B is more specific and better than Object ; however, the result goes as bad as before:

var t2 = "test" | id; // dynamic t2

Why the generic does not work? Is there any way to make the dart compiler infer it as string ?

CodePudding user response:

Your operator | extension does not have a declared return type. Its return type therefore is implicitly dynamic. Also note its callback argument does not specify a return type either, so that also will be assumed to be dynamic.

Declare return types:

extension Pipe on Object {
  Object operator |(Object Function(Object) f) => f(this);
}

(Answering your original question about a NoSuchMethodError: when you did

var x = "test" | id;
x | print;

x has type dynamic, but extension methods are static; they are compile-time syntactic sugar and will never work on dynamic types. Consequently, x | print attempts to call operator | on the object that x refers to, but that object doesn't actually have an operator |.)

  • Related