扩展递归泛型类型时类型推断失败
Broken type inference when extending recursive generic type
我处于以下情况:
interface Rec {
key: string;
children: this[];
}
type Recursive<D extends string> = {
[K in D]: string;
} & Rec;
type FlattenRecursive =
<D extends string, R extends Recursive<D>>(rs: R[]) => Omit<R, "children">[]
const flatten: FlattenRecursive =
rs => rs.flatMap(r => flatten(r.children))
我希望对 flatten
函数的递归调用被推断为 flatten<D, R>
而不是当前的 <string, R>
。因此,我不得不在调用它时显式注释类型参数:
type RValueAnimal = Recursive<"value"> & { animal: string }
const rvalues: RValueAnimal[] = [
// ...
]
flatten(rvalues) // <- error
flatten<"value", RValueAnimal>(rvalues)
我该如何解决这个问题?
[generic]https://www.typescriptlang.org/docs/handbook/2/generics.html) 函数类型的问题
<D extends string, R extends Recursive<D>>(rs: R[]) => Omit<R, "children">[]
是类型参数D
没有推理站点。您可能希望编译器能够使用 generic constraint of Recursive<D>
for the type parameter R
. Unfortunately, generic constraints do not serve as inference sites for other type parameters. There was a suggestion at microsoft/TypeScript#7234 推断出 D
来执行此操作,但它从未实现过。
这意味着当您调用这样的函数时,D
的推理将失败。因此它将回落到它自己的 string
约束,然后 R
将被约束到 Recursive<string>
,这会破坏事情。
我的建议是完全删除 D
,并纯粹用 R
来表达您关心的约束。例如:
type FlattenRecursive =
<R extends Recursive<Extract<Exclude<keyof R, keyof Rec>, string>>>(
rs: R[]) => Omit<R, "children">[]
这有点令人费解,但想法是你所说的 D
可以从 keyof R
计算出来(它应该只是 [=16] 的那些 string
键=] 也不是 Rec
的键)。您可以根据需要使用它:
flatten(rvalues); // okay
我处于以下情况:
interface Rec {
key: string;
children: this[];
}
type Recursive<D extends string> = {
[K in D]: string;
} & Rec;
type FlattenRecursive =
<D extends string, R extends Recursive<D>>(rs: R[]) => Omit<R, "children">[]
const flatten: FlattenRecursive =
rs => rs.flatMap(r => flatten(r.children))
我希望对 flatten
函数的递归调用被推断为 flatten<D, R>
而不是当前的 <string, R>
。因此,我不得不在调用它时显式注释类型参数:
type RValueAnimal = Recursive<"value"> & { animal: string }
const rvalues: RValueAnimal[] = [
// ...
]
flatten(rvalues) // <- error
flatten<"value", RValueAnimal>(rvalues)
我该如何解决这个问题?
[generic]https://www.typescriptlang.org/docs/handbook/2/generics.html) 函数类型的问题
<D extends string, R extends Recursive<D>>(rs: R[]) => Omit<R, "children">[]
是类型参数D
没有推理站点。您可能希望编译器能够使用 generic constraint of Recursive<D>
for the type parameter R
. Unfortunately, generic constraints do not serve as inference sites for other type parameters. There was a suggestion at microsoft/TypeScript#7234 推断出 D
来执行此操作,但它从未实现过。
这意味着当您调用这样的函数时,D
的推理将失败。因此它将回落到它自己的 string
约束,然后 R
将被约束到 Recursive<string>
,这会破坏事情。
我的建议是完全删除 D
,并纯粹用 R
来表达您关心的约束。例如:
type FlattenRecursive =
<R extends Recursive<Extract<Exclude<keyof R, keyof Rec>, string>>>(
rs: R[]) => Omit<R, "children">[]
这有点令人费解,但想法是你所说的 D
可以从 keyof R
计算出来(它应该只是 [=16] 的那些 string
键=] 也不是 Rec
的键)。您可以根据需要使用它:
flatten(rvalues); // okay