Issue
interface Fn {
(data: Data): void
}
interface Data<Value = any, Deps extends any[] = [...any]> {
value: Value
list: Deps
}
function fn(data: Data<string, [number]>): void {
console.log(data)
}
const foo: Fn[] = [fn]
console.log(foo)
When tested against the TypeScript Compiler this code throws an error because Type 'any[]' is not assignable to type '[number]'
.
My intuition is that the defined fn
is being assigned to the generic Data
value, but the error states that the assignment goes in the other direction. Is this a bug or limitation with the TypeScript compiler? Or how should I think about this to have a better intuition?
Solution
Vastly simplified example of the same problem:
type FruitSmasher = (fruit: 'apple' | 'orange' | 'pear') => void
const appleSmasher: FruitSmasher = (apple: 'apple') => undefined
// Type '"apple" | "orange" | "pear"' is not assignable to type '"apple"'.
appleSmasher('orange') // this is bad.
appleSmasher
is not assignable to type FruitSmasher
because fruit smasher may smash any fruit, but appleSmasher
only knows how to smash apples. So you cannot treat appleSmasher
like a FruitSmasher
.
It's backwards to your intuition here because Fn
here needs to be callable with any[]
as the Deps
. That means [123]
, or ['asd', 123]
or []
all need to be allowed as the Deps
in order to be considered the same type as Fn
.
However, fn
actually requires Deps
be [number]
, which means that any[]
isn't going to going to work.
So according to the type of Fn
. This should be valid:
function fn(data: Data<string, [number]>): void {
console.log(data.list[0].toString()) // this will crash
}
const foo: Fn[] = [fn] // ignore this very valid type error for now
// Valid for type `Fn`, catastrophic for function `fn`.
foo[0]({ value: 123, list: [] })
However fn
's Deps
are now unsatisfied. data.list[0]
would return undefined
, then would crash on .toString()
.
So yes [number]
is assignable to any[]
. But when the argument to a function is declared as any[]
, then anything more specific than that will break that since that function can't be guaranteed the type that it requires.
Answered By - Alex Wayne
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.