Reputation: 12162
var A: { [key: string]: string }
var B: { foo: string } = { foo: 'hahah' }
A = B // ok
var C: (state: { [key: string]: string; }) => void
var D = (state: { foo: string }) => {}
C = D // throw error
Cause A = B
is ok, so I think { foo: string }
is compatible with {
[key: string]: string }
But C = D
will throw an error that said Types of parameters 'state' and 'state' are incompatible.Property 'foo' is missing in type '{ [key: string]: string; }' but required in type '{ foo: string; }'.
Please tell me why?
Upvotes: 1
Views: 147
Reputation: 37986
Before we start, let's fix the return type of C
- it should be void
(instead of {}
) because D
doesn't return anything.
Now you get this error only with --strictFunctionTypes
compiler option enabled.
Look at this in the following way:
Function C
(in its parameter type declaration) states that it can handle objects with any keys.
Function D
- requires the parameter to have at least foo
key.
var C: (state: { [key: string]: string; }) => void
var D = (state: { foo: string }) => {
console.log(state.foo.toUpperCase())
}
C = D // error with strictFunctionTypes
C({}) // will blow up at runtime
Another way to describe the example is that the type
(x: T) => void
is bivariant (i.e. covariant or contravariant) forT
in default type checking mode, but contravariant forT
in strict function types mode.
More info here
Upvotes: 4
Reputation: 276125
Because A = B
doesn't mean B = A
. :
var A: { [key: string]: string }
var B: { foo: string } = { foo: 'hahah' }
A = B // ok
var C: (state: { [key: string]: string; }) => {}
var D = (state: { foo: string }) => {}
C = D // throw error
// Because
B = A // Error
Upvotes: 1