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 |
.)