javascript - TypeScript:难以键入可以在对象内部的特定级别进行过滤同时保留其原始结构的函数
问题描述
我有一个名为的对象myCached
,它的类型被称为
interface MyCache {
a: {
b: {
c: Target[];
d: string;
};
};
}
Target
项目在特定级别的属性之一中的类型在哪里,这种类型Target
也是已知的。假设Target
是这样的
type Target = "toRemove1" | "toRemove2" | "toPreserve1" | "toPreserve2";
在这里的例子中,myCache
是
const cache: MyCache = {
a: {
b: {
c: ['toRemove1', 'toPreserve1', 'toRemove2', 'toPreserve2'],
d: "irrelevant"
},
}
}
我有一系列需要删除的项目。它们也有如下Target
类型
const thingsToRemove: Target[] = ["toRemove1", "toRemove2"];
我正在尝试提出一个可以遍历这个对象并过滤掉特定级别的项目的函数。我设计这个函数的方式是它接受一个transformer对象并遍历该对象并提供过滤功能。我想正确键入它,以便此函数的用户可以回复 TS 编译器提供的自动完成功能并进行类型检查以确保此函数正确落在正确的级别上,在本例中是Target
级别。
这是我的代码
type MappedTransform<T> = {
[K in keyof T]?: MappedTransform<T[K]> | ((params: T[K]) => T[K]);
};
type Entries<T> = { [K in keyof T]-?: [K, T[K]] }[keyof T];
function traverse<R>(cache: R, transformObject: MappedTransform<R>): R {
return (Object.entries(transformObject) as Array<
Entries<MappedTransform<R>>
>).reduce(reduceTransformNode, cache);
}
const reduceTransformNode = <R, K extends keyof R>(
cacheNode: R,
[transformKey, transformValue]: [
K,
MappedTransform<R[K]> | ((params: R[K]) => R[K]) | undefined
]
): R => {
const { [transformKey]: node } = cacheNode;
if (typeof transformValue === "undefined") return cacheNode;
const newCacheValue =
typeof transformValue === "function"
? (transformValue as (params: R[K]) => R[K])(node)
: traverse(transformValue as R[K], node);
return {
...cacheNode,
[transformKey]: newCacheValue
};
};
const x = traverse(cache, {
a: {
b: {
// Need to use Type `Target` to make sure that the transformer function lands on the type of `Target` exactly
c: (node) => node.filter((s) => !thingsToRemove.includes(s))
}
}
});
这工作正常,我已经非常接近我想要实现的目标,除了我似乎无法找到添加类型的方法Target
以确保用户提供的用于执行过滤的功能实际上处于正确的级别,node
即正确的类型Target
这是现场演示。有人能告诉我如何实现我在这里寻求的最后一点类型安全吗?
解决方案
推荐阅读
- postgresql - 邮递员。锁定监视所有在关系字段中具有名称的数据库
- c - snprintf 在被复制的字符串中使用格式说明符
- python - 不同大小的列表比较
- django - 如何为 django rest API 生成静态 api 文档?
- yarnpkg - 本地 Lerna 包的未找到纱线错误
- android - Gradle 同步失败 - Android Studio
- c# - 如何在 DataContext (INotifyPropertyChanged) 属性 (WPF - C# - XAML) 上设置点击事件?
- informix - 如何设置文本文件数据中不包含的附加字段的值?
- jdbc - Kafka 源 - 接收器连接器 - 具有单个主题的多个表
- amazon-web-services - 列出所有密钥时忽略 AWS 托管/默认 KMS 密钥?