javascript 类型参数“T”具有循环约束

lnlaulya  于 2023-01-07  发布在  Java
关注(0)|答案(2)|浏览(162)

我试图创建一个泛型类型,它将由参数类型和一个数组组成,该数组位于nodes之下。

type Foo<T> = T & {
    nodes: Foo<T>[]
}

function Bar<A extends Foo<A>>():null{
    return null;
}

当我试着运行它的时候,我得到了
类型参数"A"具有循环约束
我明白。问题是,这正是我想要的。我想这样使用它:

interface Vegetables{
    id:number
    nodes: Vegetables[]
}

interface Fruits{
    id:number
    nodes: Fruits
}

Bar<Vegetables>()
Bar<Fruits>

我不知道我错过了什么
代码示例

avwztpqn

avwztpqn1#

好吧,我找到了一个变通办法。
因为我们要扩展,所以我们保留T。所以这应该仍然有效

type Foo<T> = {
    nodes: Foo<T>[]
}

function Bar<A extends Foo<A>>():null{
    return null;
}

// desired usage:

interface Vegetables{
    id:number
    nodes: Vegetables[]
}

interface Fruits{
    id:number
    nodes: Fruits[]
}

Bar<Vegetables>()
Bar<Fruits>

但是如果有人有办法让它以原来的方式工作,请留下回应

0h4hbjxa

0h4hbjxa2#

尚不清楚此类型参数的用途,但我感觉您希望此操作失败

interface Stuff {
    id:number
    nodes: Vegetables[]
    type: 'stuff' // adding a discriminant so that Stuff ≠ Vegetables
}

// @ts-expect-error: Stuff is not Stuff & { nodes: Stuff[] }
Bar<Stuff>()

虽然不漂亮,但你可以这样做

function Bar<
    A extends Foo<unknown> & Check,
    Check = A extends Foo<A> ? unknown: never
>():null{
    return null;
}

由于unknown是交集的中性元素,因此当满足约束时Check不影响第一类型参数,并且由于此条件不返回A,因此它不是循环约束。
现在,当不满足约束时,您不需要返回never,任何与Foo<unknown>不兼容的类型都将是错误的,因此您可以返回一些错误消息,解释A应该是递归的。

相关问题