假设我正在用TypeScript构建一个最小的编译器:
我有适用于不同类型文件的解析器:
interface Parser<ParsedTree extends object> {
parse(buffer: Buffer): ParsedTree;
}
我有一些转换,可能会或可能不会突变已解析文件树的访问节点:
interface Transform<Node, TransformedNode> {
pre(node: Node): TransformedNode;
post(node: Node): TransformedNode;
}
我有目标,它们接受转换后的树,并对其进行处理(表面上将它们写入fs):
interface Target<TransformedTree> {
write(tree: TransformedTree): void;
}
目标的TransformedTree
类型应从转换返回的内容中得出。再说一次,我们得到每个变换的pre
和post
的并集返回类型,并将其添加到已解析的树节点类型上。为此,我们获取了解析器的返回类型,然后使用以下实用程序类型将每个树类型的节点变成其自身的并集以及所有转换的pre
和post
的返回类型方法:
export type ChildrenUnionWith<T, Append> = {
[K in keyof T]: T[K] extends object
? ChildrenUnionWith<T[K], Append> | Append
: T[K] | Append;
};
同时,通过使用以下实用程序获取所有Transform
的节点的并集,我们得到了ParsedTree
的第一个通用参数:
export type NodeOfTree<Tree> = Tree extends object
? ({[K in keyof Tree]: NodeOfTree<Tree[K]>}[keyof Tree] | Tree)
: Tree;
我试图将这些类型拼凑成这样:
function compile<
Parsers extends Parser<object>[],
Transforms extends Transform<NodeOfTree<ParsedTree>, unknown>[],
Targets extends Target<TransformedTree>[],
ParsedTree = ReturnType<Parsers[number]["parse"]>,
TransformedNode = ReturnType<Transforms[number]["pre" | "post"]>,
TransformedTree = ChildrenUnionWith<ParsedTree, TransformedNode>
>(parsers: Parsers, transforms: Transforms, targets: Targets) {
// do something
}
这可行...但是在运行时使用中,给定的Transform
可能会作用于先前已转换的节点上。因此,我想将所有转换的返回类型通过管道传递回其第一个通用参数...我希望节点类型为–不仅是所有ParsedTree
节点的并集,以及所有Transform
pre
和post
返回类型的并集。
以下内容无法按预期运行:
function compile<
Parsers extends Parser<object>[],
Transforms extends Transform<NodeOfTree<ParsedTree> | TransformedNode, unknown>[],
Targets extends Target<TransformedTree>[],
ParsedTree = ReturnType<Parsers[number]["parse"]>,
TransformedNode = ReturnType<Transforms[number]["pre" | "post"]>,
TransformedTree = ChildrenUnionWith<ParsedTree, TransformedNode>
>(parsers: Parsers, transforms: Transforms, targets: Targets) {
// do something
}
当我通过以下参数时...
compile(
[{parse: (_: Buffer) => ({a: "b", c: "d"})}],
[
{
pre: (node) => {},
post: (node) => {},
},
],
[{write: (node) => {}}],
);
...不仅没有类型错误,而且node
和pre
中的post
类型是any
:/
有人对我如何启用要查找的文字有任何建议吗?
谢谢!