kaijun
kaijun

Reputation: 12162

TypeScript function type compatibility

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

Answers (2)

Aleksey L.
Aleksey L.

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) for T in default type checking mode, but contravariant for T in strict function types mode.

More info here

Upvotes: 4

basarat
basarat

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

Related Questions