Typescript 使用泛型扩展接口不再可分配给父级

Typescript 使用泛型扩展接口不再可分配给父级,typescript,generics,typescript2.0,typescript2.4,Typescript,Generics,Typescript2.0,Typescript2.4,我最近升级到了typescript 2.4,我收到了几个错误,抱怨我的类型不再可分配 下面是我遇到错误的场景: interface Parent { prop: any } interface Child extends Parent { childProp: any } type Foo<T> = <P extends Parent>(parent: P) => T function createFooFunction<T>(ar

我最近升级到了typescript 2.4,我收到了几个错误,抱怨我的类型不再可分配

下面是我遇到错误的场景:

interface Parent {
    prop: any
}

interface Child extends Parent {
    childProp: any
}

type Foo<T> = <P extends Parent>(parent: P) => T

function createFooFunction<T>(arg: T): Foo<T> {
    // Error here!
    return (child: Child): T => {
        return arg;
    }
}
虽然这不是一个理想的解决方案,因为在我的情况下,childProp是必需的

我还注意到,将Foo的参数类型直接更改为Parent也将满足typescript,即进行此更改

interface Child extends Parent {
    childProp?: any
}
type Foo<T> = (parent: Parent) => T
type Foo=(父对象:父对象)=>T
但这也不是一个解决方案,因为我既不控制Foo类型,也不控制父对象。它们都来自vendor.d文件,因此我无法修改它们

但不管怎样,我都不知道为什么这是一个错误。Foo类型表示它需要扩展父对象的东西,而子对象就是这样一个对象,那么为什么typescript会认为它不可赋值呢

编辑:我已将此标记为已回答,因为添加
--noStrictGenericChecks
标志将抑制错误()。然而,我仍然想知道为什么这是一个错误,因为我宁愿保持严格的检查和重构我的代码,如果它是错误的,而不仅仅是短路它


再次重申问题的核心,既然Child扩展了Parent,为什么typescript不再认为Child可以分配给Parent,而就OOP泛型而言,为什么这比以前更正确?

版本2.4引入了更严格的泛型检查

阅读本文并查找标题对泛型进行更严格的检查

从文章中:

作为任何破损的临时解决方法,您可以使用新的
--noStrictGenericChecks
标志来抑制其中一些错误


它还为回调引入了严格的逆变。

我认为问题在于,您返回的函数需要一个
子函数作为参数,但将其分配给一个函数,该函数必须能够接受从
父函数
派生的任何内容,而不仅仅是
子函数

假设您调用
createfooofunction
a get
Foo
。根据
Foo
的定义,可以创建一个扩展
Parent
的类
Child2
,并将其作为参数传递给您得到的
Foo
。这是一个问题,因为实际返回的函数只能作为参数获取
Child
,而不能
Child2

这其实更正确。请记住,您没有将
子项
分配给
父项
。您使用的函数只需要一个
子函数
,并将其分配给一个可以使用任何类型的
父函数
。这是非常不同的。另一方面,如果我们处理的是一个返回值而不是一个输入,这就可以了。这是协方差和反方差之间的差异,在开始时可能会有点混淆。在C#中,您可以使用
In
out
关键字在自己的泛型类中指定这一点

例如,在C#中,如果你有一个
IEnumerable
(声明为
IEnumerable
),它自然也是一个
IEnumerable
,因为你在迭代,你得到的是
子对象,你也可以得到
父对象,因为每个
子对象也是
父对象。因此,您可以将
IEnumerable
指定给
IEnumerable
,但不能反过来!因为你不能保证得到一个
子对象

另一方面,如果您有类似于
IComparer
(声明为
IComparer
)的东西,它可以比较两个
Parent
对象-因为每个
子对象也都是
父对象
,它还可以比较任意两个
子对象。因此,您可以将
IComparer
分配给
IComparer
,但不能反过来分配-可以比较
子项的东西只知道如何比较
子项
!这是你的问题

您可以将
in
out
理解为回调中的输入(参数)和输出(返回)值。您只能使输入更具体(反向方差),输出更一般(协方差)

顺便说一句,我认为

在这里是完全无用的(这增加了混乱),因为您可以在该函数中传递任何扩展
Parent
的内容,即使它不是泛型的。只有当您像这样返回类型时,这才有用:

(Parent:P)=>P

,以在返回值中保留正确的类型
P
。如果没有泛型,您必须接受
Parent
并返回
Parent
,这样即使您输入了更具体的内容,您也会得到一个
Parent
。至于如果去掉这个,错误为什么会消失,我真的不知道。

添加--noStrictGenericChecks确实抑制了错误,所以我将此标记为已回答。
type Foo<T> = (parent: Parent) => T