Parameter 'm' implicitly has an 'any' type - angular

I am getting an error while running my project.
This is the code :
private populateModels() {
var selectedMake = this.makes.find(m => m.id == this.vehicle.makeId);
this.models = selectedMake ? selectedMake.models : [];
}
Here is the error:
ERROR in [at-loader] ./ClientApp/app/components/vehicle-form/vehicle-form.component.ts:82:40
TS7006: Parameter 'm' implicitly has an 'any' type.

You can just add a type to your m variable this way:
private populateModels() {
var selectedMake = this.makes.find( (m: any) => {
m.id == this.vehicle.makeId);
});
this.models = selectedMake ? selectedMake.models : [];
}
So you have to add m: any or m: vehicle depending on the type you are using for your model. and this error will disapear.

Related

TypeScript compile error TS2322 when assigning a value of a generic type

I am trying to create a TypeScript function that has two type parameters, where one type parameter uses the other one:
interface Wrapper<T> {
value: T;
}
function func<T, W extends Wrapper<T>>(val: T, takesWrapper: (w: W) => void) {
const wrapper: W = { value: val };
takesWrapper(wrapper);
}
func(32, num => { console.log(Math.abs(num.value) + 10); });
The TypeScript compiler yields an error for the line const wrapper: W = { value: val };:
test.ts(6,11): error TS2322: Type '{ value: T; }' is not assignable to type 'W'.
However, as W extends Wrapper<T>, the assigned value { value: val } where val is of type T should be valid.
Why does the TypeScript compiler yield a compile error in this case?
You're creating object that might be not assignable to W. For example:
interface ExtendedWrapper<T> extends Wrapper<T>{
anotherValue: T;
}
{ value: 1 } is not assignable to ExtendedWrapper<number> (property anotherValue is missing).
You can overcome this using type assertion const wrapper = { value: val } as W; but keep in mind that takesWrapper function expects extended type.

Is this a bug or feature? im not sure

not sure, is should post this here, but this is place where i landed...
error messages in comments are shown at lines bellow them. Why these errors are shown? Specially error #1 because T extends ITest so it should be safe cast...
interface ITest {
answer?: number; // error #1 dissapears if '?' is removed
}
class Base<T> {
obj: T;
}
class Derived<T extends ITest> extends Base<T> {
constructor() {
super();
var obj = { answer: 42 };
// ok ... no suprise here
var test:ITest = obj as ITest;
// #1 Neither type { answer: number } or type T is assignable to each other.
var t:T = obj as T;
// this works ... (why? - specially when 1. dont...)
var t2:T = obj as ITest as T;
// #2 Type { answer: number } is not assignable to type 'T'.
// #3 Cannot convert type { answer: number } to type T. Type parameter T is incompatible with { answer: number }, with is not type parameter.
this.obj = obj;
// #4 Type ITest is not assignable to type 'T'.
// #5 Cannot convert type ITest to type T. Type parameter T is incompatible with ITest, with is not type parameter.
this.obj = test;
// this works
this.obj = obj as any;
// in this case error is not shown even if 'answer' is required in ITest ...
// (expected: 'Type { totally: string } is not assignable to type 'T'.)
this.obj = { totally: 'different' } as any;
}
}
cheers
It seems that all of those errors come from two issues, but before we get to them you need to understand how typescript compares types, and that's using duck typing (more on duck typing):
One of TypeScript’s core principles is that type-checking focuses on
the shape that values have. This is sometimes called “duck typing” or
“structural subtyping”
In your code you do this:
var obj = { answer: 42 };
Here obj isn't an ITest, its' type is { answer: number }, and the compiler will match that to ITest when it can, but that doesn't make obj to be of type ITest.
If you want it to be ITest you need to do:
var obj = { answer: 42 } as ITest;
Or
var obj: ITest = { answer: 42 };
If you define obj to be ITest then error #1 is gone (with or without the optional property), which is also why you don't get an error here:
var t2: T = obj as ITest as T;
The rest of your errors are due to the fact that T isn't ITest, it extends it.
For example if I have:
interface ITest2 extends ITest {
question: string;
}
let c = new Derived<ITest2>();
Then now this:
var obj: ITest = { answer: 42 };
...
this.obj = obj;
Is problematic, as obj is of type ITest but this.obj needs to be of type ITest2.
You can tell the compiler to trust that you know what you're doing:
this.obj = obj as T;
this.obj = test as T;
(your code with no error in playground)
When you cast to any then you basically tell the compiler not to type check, so that's why you don't get an error for:
this.obj = { totally: 'different' } as any;

Typescript cannot detect parameter types on generic methods in index signatures

I have an interface defining an index signature:
interface MethodCollection {
[methodName: string]: (id: number, text: string) => boolean | void;
}
Everything's good here, any method I add to such an object will have their parameter types recognized correctly:
var myMethods: MethodCollection = {
methodA: (id, text) => {
// id: number
// text: string
}
}
Now, I need to add a type parameter to these functions:
interface MethodCollection {
[methodName: string]: <T>(id: number, text: string, options: T) => boolean | void;
}
The moment I do this, the TypeScript compiler barfs up:
Parameter 'text' implicitly has 'any' type
Parameter 'options' implicitly has 'any' type
Parameter 'id' implicitly has 'any' type
And indeed, neither can IntelliSense trace the correct types any longer, they all become implicit any:
var myMethods: MethodCollection = {
methodA: (id, text, options) => {
// id: any
// text: any
// options: any
}
}
Why is this happening? How can I use generic methods with an index signature? I'm using Visual Studio 2013, my project is set to use TypeScript version 1.6.
You can make the type inference work by making the interface generic, and specify it when creating the variable.
interface MethodCollection<T> {
[methodName: string]: (id: number, text: string, options: T) => boolean | void;
}
var myMethods: MethodCollection<string> = {
methodA: function(id, text, options) {
// id :number,
// text: string,
// options: string
}
}
With VSCode and tsc 1.9.0 (current typescript#next), it's the only way it works.
That wouldn't allow you to have different types for different methods though.
You can however give an optional type to the MethodCollection.
var myMethods: MethodCollection<string | boolean> = {
methodA: function(id, text, options) {
// options is string | boolean
}
}

Swift: Failed to assign value to a property of protocol?

Class A provides a string value. Class B has two members of A type inside itself, and provide a computed property "v" to choose one of them.
class A {
var value: String
init(value: String) {
self.value = value
}
}
class B {
var v1: A?
var v2: A = A(value: "2")
private var v: A {
return v1 ?? v2
}
var value: String {
get {
return v.value
}
set {
v.value = newValue
}
}
}
This code is simple and it works. Since both the A and B have a member "value", I make it a protocol like this:
protocol ValueProvider {
var value: String {get set}
}
class A: ValueProvider {
var value: String
init(value: String) {
self.value = value
}
}
class B: ValueProvider {
var v1: ValueProvider?
var v2: ValueProvider = A(value: "2")
private var v: ValueProvider {
return v1 ?? v2
}
var value: String {
get {
return v.value
}
set {
v.value = newValue // Error: Cannot assign to the result of the expression
}
}
}
If I change the following code
v.value = newValue
to
var v = self.v
v.value = newValue
It works again!
Is this a bug of Swift, or something special for the property of protocols?
You have to define the protocol as a class protocol:
protocol ValueProvider : class {
var value: String {get set}
}
Then
var value: String {
get { return v.value }
set { v.value = newValue }
}
compiles and works as expected (i.e. assigns the new value to the
object referenced by v1 if v1 != nil, and to the object
referenced by v2 otherwise).
v is a read-only computed property of the type ValueProvider.
By defining the protocol as a class protocol the compiler knows
that v is a reference type, and therefore its v.value
property can be modified even if the reference itself is a constant.
Your initial code example works because there the v property has
the type A which is a reference type.
And your workaround
set {
var tmp = v1 ?? v2
tmp.value = newValue
}
works because (read-write) properties of variables can be set in
any case (value type or reference type).

Returning Akka.Future - Play Framework

In the following piece of code, I'm trying to return an Async result which is an Akka.future in this case. When I tried to map the result for the method's response, I get a compile error that says
[error] Test.scala:180: type mismatch;
[error] found : scala.concurrent.Future[play.api.mvc.SimpleResult[String]]
[error] required: play.api.mvc.Result
[error] jsonResponse.map((s: String) => Ok(s))
Here is what I tried:
def testAkka(jsonList: List[String]) = Action {
Async {
val ftrList: List[Future[String]] = jsonList.map((s: String) => Akka.future {returnSomeVal(s)} )
val futureList: Future[List[String]] = Future.sequence(ftrList)
val jsonResponse: Future[String] = futureList.map((f: List[String]) => f.mkString(","))
Akka.future {
jsonResponse.map((s: String) => Ok(s)) // Compiler complains here
//Ok(jsonResponse)
}
}
}
Use jsonResponse.flatMap, instead of map

Resources