Gio*_*zas 2 javascript typescript
为什么这在打字稿中不起作用?
class Parent {
id: string = ''
}
class Child extends Parent{
name: string = ''
}
const fails: (created: Parent) => void = (created: Child) => { return };
const failsToo: ({ created }: { created: Parent }) => void = ({ created }: { created: Child }) => { return };
Run Code Online (Sandbox Code Playgroud)
至少对我来说这个错误很奇怪:
Type '(created: Child) => void' is not assignable to type '(created: Parent) => void'.
Types of parameters 'created' and 'created' are incompatible.
Property 'name' is missing in type 'Parent' but required in type 'Child'
Run Code Online (Sandbox Code Playgroud)
看起来它正在尝试将Parent 分配给 Child,但实际代码中是向后的(尝试将作为 Child 的方法参数分配给 Parent。这是有道理的,因为 Child 是 Parent 的超集)
我错过了什么吗?
函数类型在其参数类型上是逆变的。类型相反。 它们的变化方向彼此相反。所以如果A extends B,那么((x: B)=>void) extends ((x: A)=>void),不是((x: A)=>void) extends ((x: B)=>void)。这是类型论的自然结果,但是您可以通过想象尝试将比预期更窄/更宽的类型传递给函数并看看会发生什么来说服自己这种必要性。例如,假设这成功了:
const fails: (created: Parent) => void =
(created: Child) => { created.name.toUpperCase() };
Run Code Online (Sandbox Code Playgroud)
该功能(created: Child) => { created.name.toUpperCase() }本身就很好;它接受 aChild并访问其name属性,即 a string,因此它有一个toUpperCase()方法。但您已将其分配给类型为 的变量(created: Parent) => void。这意味着你可以fails()这样调用:
fails(new Parent()); // okay at compile time, but
// RUNTIME ERROR! created.name is undefined
Run Code Online (Sandbox Code Playgroud)
如果fails()接受任何Parent,那么您可以将它传递给new Parent()不是 a 的 a Child。但是现在您遇到了运行时错误,因为在运行时您试图访问您所提供的实例的toUpperCase()不存在name属性的方法。Parent糟糕,我们在某个地方犯了一个错误。
错误恰恰在于您无法扩展函数所需的类型。如果您启用了编译器选项(--strictFunctionTypes建议这样做),TypeScript 将有助于报告此类不正确的参数扩展的错误。
您不能扩大参数类型,但可以缩小它。如果你有一个GrandChild子类,你就可以毫无问题地做到这一点:
class GrandChild extends Child {
age: number = 1;
}
const okay: (created: GrandChild) => void =
(created: Child) => { created.name.toUpperCase() };
okay(new GrandChild()); // okay
Run Code Online (Sandbox Code Playgroud)
这很好,因为okay()只能接受GrandChild实例,每个实例也是一个Child实例,这是函数实现所期望的。该实现不知道它被赋予了GrandChildren,因此它无法访问该age属性,但这样做是安全的。
经验法则是,当类型出现在输入位置(如函数参数)时,类型方差的方向与其在输出位置的方向相反。
| 归档时间: |
|
| 查看次数: |
653 次 |
| 最近记录: |