Typescript array.map 没有正确分配交集类型
Typescript array.map doesn't distribute intersection types properly
我有一个类型为 object[] & Tree[]
的数组,但是 arr.map(child => ...)
将 child 的类型推断为 object
而不是 object & Tree
。
有什么方法可以避免这种情况而无需额外的转换?
值得注意的是 Tree
扩展了 object
但打字稿似乎没有意识到这一点并合并了交集类型的两个部分。
编辑 - 最小可重现示例:
这是人为的,但基于我最近的另一个问题 Transform a typescript object type to a mapped type that references itself
interface BasicInterface {
name: string;
children: object[];
}
function getBasic<T extends object>(input: T): BasicInterface {
return input as BasicInterface;
}
export const basicTree = getBasic({
name: 'parent',
children: [{
name: 'child',
children: []
}]
});
重点是下面的代码可以访问 "basicTree" 及其推断类型。对于这个例子,我定义了
BasicInterface,但实际上这是自动生成的,我还没有找到一种方法来编程
生成一个递归接口。
我想将 children 的递归类型添加回原来的接口定义。
与其在代码中完全重新定义 BasicInterface,因为这可能有很多样板,我正在尝试
"enhance" 具有正确递归定义的 basicTree 类型的定义。
但是在获取 children 的类型时,这会下降。也许有更简单的解决方案?
type RestoredInterface = typeof basicTree & {
children: RestoredInterface[]
};
function getTree(basic: BasicInterface): RestoredInterface {
return basic as RestoredInterface;
}
const restoredTree = getTree(basicTree);
const names = restoredTree.children.map(child => child.name);
我找到了一个奇怪的解决方案。只需更改声明中的顺序即可。这很奇怪,但它有效:
type RestoredInterface = {
children: RestoredInterface[]
} & typeof basicTree;
编辑:这是一个 explanation。
更好的解决方案可以是这样的:
type RestoredInterface = Omit<typeof basicTree, 'children'> & {
children: RestoredInterface[]
};
根据 jcalz 的观察,实际上可以简单地扩展原始接口。我很困惑,因为它是以编程方式定义的,但如果你先命名它,那不是问题:
type BasicTreeInterface = typeof basicTree;
interface RestoredInterface extends BasicTreeInterface {
children: RestoredInterface[]
};
const restoredTree = getTree(basicTree);
const names = restoredTree.children.map(child => {
// Child is of type RestoredInterface
});
我有一个类型为 object[] & Tree[]
的数组,但是 arr.map(child => ...)
将 child 的类型推断为 object
而不是 object & Tree
。
有什么方法可以避免这种情况而无需额外的转换?
值得注意的是 Tree
扩展了 object
但打字稿似乎没有意识到这一点并合并了交集类型的两个部分。
编辑 - 最小可重现示例:
这是人为的,但基于我最近的另一个问题 Transform a typescript object type to a mapped type that references itself
interface BasicInterface {
name: string;
children: object[];
}
function getBasic<T extends object>(input: T): BasicInterface {
return input as BasicInterface;
}
export const basicTree = getBasic({
name: 'parent',
children: [{
name: 'child',
children: []
}]
});
重点是下面的代码可以访问 "basicTree" 及其推断类型。对于这个例子,我定义了 BasicInterface,但实际上这是自动生成的,我还没有找到一种方法来编程 生成一个递归接口。
我想将 children 的递归类型添加回原来的接口定义。
与其在代码中完全重新定义 BasicInterface,因为这可能有很多样板,我正在尝试 "enhance" 具有正确递归定义的 basicTree 类型的定义。
但是在获取 children 的类型时,这会下降。也许有更简单的解决方案?
type RestoredInterface = typeof basicTree & {
children: RestoredInterface[]
};
function getTree(basic: BasicInterface): RestoredInterface {
return basic as RestoredInterface;
}
const restoredTree = getTree(basicTree);
const names = restoredTree.children.map(child => child.name);
我找到了一个奇怪的解决方案。只需更改声明中的顺序即可。这很奇怪,但它有效:
type RestoredInterface = {
children: RestoredInterface[]
} & typeof basicTree;
编辑:这是一个 explanation。
更好的解决方案可以是这样的:
type RestoredInterface = Omit<typeof basicTree, 'children'> & {
children: RestoredInterface[]
};
根据 jcalz 的观察,实际上可以简单地扩展原始接口。我很困惑,因为它是以编程方式定义的,但如果你先命名它,那不是问题:
type BasicTreeInterface = typeof basicTree;
interface RestoredInterface extends BasicTreeInterface {
children: RestoredInterface[]
};
const restoredTree = getTree(basicTree);
const names = restoredTree.children.map(child => {
// Child is of type RestoredInterface
});