我对您的需求的理解是:
- 你有一些实体,比如说用户
- 您想要创建可用于不同实体的通用过滤器类型
- 通用过滤器类型应该对每个实体都是类型安全的
首先让我们定义我们需要过滤的可能规则
type Rule<T> = { $eq: T } | { $gte: T } // append any other rules you need
我从您的示例中提取了两条规则 - $eq 和 $gte 但您可以通过 | 添加您需要的其他规则。
其次让我们定义泛型Filter 类型
type Filter<Obj> = {
[K in keyof Obj]: Rule<Obj[K]>
}
我们的类型说 - 我应该拥有给定对象的所有键,并且我应该为每个键定义一个规则,该规则适用于与此属性相同的类型。所以对于属性a: string,规则需要是或{$eq: string}或{$gte: string}。
让我们看一个例子:
// example filter for the User type
type User = {
id: number;
name: string;
}
// create an instance of the filter for the User entity
const userFilter: Filter<User> = {
id: { $gte: 1 }, // rule needs to have value as number
name: {$eq: '2'} // rule needs to have value as string
}
// what if we want to filter by only part of the interface - use Pick utility type
const userFilter2: Filter<Pick<User, 'name'>> = {
name: {$eq: '2'} // only name is needed to be provided
}
类型Filter 是完全类型安全的,通过创建这种类型的实例,我们需要为这些键定义正确的键和正确的规则。
作为补充,您可以有条件地说明哪些规则适用于哪些类型。假设$gte 仅适用于数字,但不适用于其他类型。你可以这样做:
type Rule<T> = T extends number ? { $eq: T } | { $gte: T } : { $eq: T }
以上定义将阻止将$gte 用于除数字以外的任何内容。