此"类型 'any[]' 不可分配给类型"[数字]"打字稿错误的原因是什么?


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)

当针对TypeScript编译器进行测试时,此代码抛出一个错误,因为Type 'any[]' is not assignable to type '[number]'

我的直觉是,定义的fn被分配给通用的Data值,但错误表明分配朝着另一个方向进行。这是TypeScript编译器的错误还是限制?或者我应该如何思考才能有更好的直觉?

相同问题的大量简化示例:

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不能归属于FruitSmasher类型,因为水果粉碎器可以粉碎任何水果,但appleSmasher只知道如何粉碎苹果。因此,您不能像对待FruitSmasher那样对待appleSmasher

游乐场


这是你的直觉,因为这里的Fn需要用any[]作为Deps来调用。这意味着[123]、或['asd', 123][]都需要被允许作为Deps以便被认为是与Fn相同的类型。

然而,fn实际上要求Deps[number],这意味着any[]不起作用。

因此根据CCD_ 21。这应该是有效的:

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: [] })

然而,fnDeps现在并不满意。data.list[0]将返回undefined,然后在.toString()上崩溃。

所以是的,CCD_ 27可分配给CCD_ 28。但是,当函数的参数被声明为any[]时,任何比这更具体的都会破坏这一点,因为该函数无法保证其所需的类型。

下面是发生的事情。您为Data类型声明接口,表示该类型的第二个值是一个可以具有任何类型的数组:

interface Data<Value = any, Deps extends any[] = [...any]> {
value: Value
list: Deps
}

然后你使用数据类型,但说第二个值将是一个数字数组:

function fn(data: Data<string, [number]>): void {
console.log(data)
}

因此,类型表示数组可以是任何东西,但函数声明表示Data类型保证数组只能是数字,因为您正在将符合Data接口的对象传递到无法接受该接口的某些可能形式的对象中。

请记住,typescript实际上只在IDE和编译器中起作用。它最终被构建到JavaScript中,JavaScript是一种没有数据类型的解释语言。这意味着,如果您试图在编译函数fn后将数组中包含字符串的对象传递给它,那么它实际上不会抛出错误,因此IDE和编译器需要标记它并拒绝接受结构问题。

相关内容

最新更新