Cannot convert type value of type Observable<Store> to expected argument type Observable<Store?> - swift

I'm getting an error which says the following:
Cannot convert value of type 'Observable<Store>' to expected argument type 'Observable<Store?>
So the method I'm calling StoreMock(state: stateSubject, store: storeSubject) seems to expect an optional for the observable storeSubject. But I'm not sure why it should matter if I pass in a non-optional. Shouldn't it be fine as it will always be there.
Any ideas?

You have to wrap the object into an Optional:
StoreMock(state: stateSubject, store: storeSubject.map(Optional.some))
Just one call will fix this.

Related

Can not satisfy generic constraint with subclass?

I have following compiler error:
Cannot convert value of type ‘PostTagViewModel<CreatePostMediaViewModel>’ to expected argument type ‘PostTagViewModel<PostMediaViewModel>’
CreatePostMediaViewModel is subclass of PostMediaViewModel, so on the first glance it seemed like this should work out of the box, but sadly it does not?
EDIT:
Some addtional info, swift array is generic and I can pass [Subclass] where parameter is declared [Baseclass]

Why direct usage of generic value is not possible but same is possible if returned from method in Dart

Why is it assigning a value to a generic field is not possible when assigned directly, but same is possible when using a variable reference or method return value (here, same value is assigned to the variable and method returns the same value)?
class User {}
class Teacher extends User {}
class Student extends User {}
Future<User> getUser() {
return Future.value(Student());
}
void main() {
Future<Future<User>> fut = Future.value(getUser()); // <----- No error
Future<Future<User>> fut2 = Future.value(Future.value(Student())); // <----- Getting error
Future<User> userFut3 = Future.value(Student());
Future<Future<User>> fut3 = Future.value(userFut3); // <----- No error
}
Getting below error when Future.value(Future.value(Student())) assigned directly.
Error: The argument type 'Student' can't be assigned to the parameter type 'FutureOr<Future<User>>?'.
The issue here is that the parameter of Future<T>.value has the type FutureOr<T>. It can be either a future or a value.
Also, Dart type inference works by "pushing down" a context type, then trying to make the expression work at that type, and finally pushing the final static type back up.
If an expression like Future.value(...) has a context type, the missing type argument is always inferred from the context type.
When you write
Future<Future<User>> fut2 = Future.value(Future.value(Student()));
the context type of the outer Future.value, the type we know it should have, is Future<Future<User>>. That makes its argument have context type FutureOr<Future<User>>.
The argument is Future.value(Student()), where we don't yet know anything about Student() because we haven't gotten to it in the type inference yet, we're still working out way down towards it.
A Future<X> can satisfy that FutureOr<Future<User>> in two ways, either by being a Future<User> or by being a Future<Future<User>>.
Type inference then guesses that it's the latter. It's wrong, but it can't see that yet. The way type inference works, it has to use the context type when there is one, but the context type is ambiguous, and it ends up choosing the wrong option.
You are hitting an edge case of the type inference where the context type can be satisfied in two different ways, and the downwards type inference chooses the wrong one. It's a good heuristic that if you have a FutureOr<...> context type, and you see a Future constructor, you want the Future-part of the FutureOr<...>. It breaks down when you have FutureOr<Future<...>>. So, don't do that!
My recommendation, in complete generality, is to never have a Future<Future<anything>> in your program. Not only does it avoid problems like this, but it's also a better model for your code.
A future which eventually completes to something which eventually completes to a value ... just make it eventually complete to that value directly. Waiting for the intermediate future is just needless busywork.
Because in the function you defined the return type and dart knows the return type, but when assigning directly dart does not know Future.value(Student()) has a type of Future<User>. to fix this you have to tell the dart the type of the value, like this: Future.value((Future.value(Student())) as Future<User>);
this way dart will know the type of this value and treat it as a Future<User>.

The name 'string' isn't a type and can't be used in an 'is' expression

During unit testing of a function returning different types of objects, I need to check if the type of returned object is the same as expected. Therefore, I need to pass multiple classes inside a variable. Then I need to use this variable with the is operator to check types.
final string = String;
assert('foo' is string);
But I am getting
error: The name 'string' isn't a type and can't be used in an 'is' expression.
I read somewhere that a library called Dart:mirrors can solve this problem but I haven't seen an actual example.
In unit testing, you know the expected answer. There shouldn't be a need to make your types variables.
Instead, just assert with the strong typed
assert('foo' is String);
I found the answer. The trick to create an instance of the type that I want to assert, then use runtimeType property.
If a class is called User from a.dart and another one is also called User from b.dart, runtimeType won't be the same
final string = 'anything'.runtimeType;
assert('foo'.runtimeType is string);

Difference between wrapping a value and explicitly declaring value as a type in Swift

I came across a heterogeneous dictionary definition like this on a tutorial online:
var mixedMap4 = [AnyHashable(0): "Zero" as Any,
AnyHashable(1): 1.0 as Any,
AnyHashable("pi"): 3.14 as Any]
I was wondering why the author chose to write
AnyHashable(0) instead of 0 as AnyHashable. When I tried this on Swift playground, it also worked. However when I turned "Zero" as Any into Any(0) it gives the following
error: error: The Dictionary.xcplaygroundpage:41:34: error: protocol
type 'Any' cannot be instantiated var mixedMap4 = [AnyHashable(0):
Any("Zero") ,
Thank you for the answer
The clue is in the error message.
AnyHashable is a struct that type-erases the underlying hashable type, and so can be directly instantiated as an object
Any is a protocol and therefore can't be directly instantiated, although all other types can be complied with it, thus a String such as "Zero" can be cast as Any but Any(String) is meaningless.
To me it all just feels like a bucket load of trouble waiting to happen!

<unknown>:0: error: type 'Key' constrained to non-protocol type 'String'

Migrating to Swift 3 from 2.3 and am running into this issue. The error is traceable to a view controller.
I do not see any extensions/protocols which would require a 'Key' constrained to 'String'.
I've tried to comment out code that might be causing the error, and have had strange results - ie removing an empty viewDidLoad() made the error appear in another class.
I'll update the thread if I make progress.
Key is a type inside a structure maybe a struct/class like Dictionary.
Use AnyHashable as Key to replace String if in Dictionary.