[英]Typescript Interface With Multiple Dynamic Keys
我有一个查询 MongoDB 数据库的应用程序,但目前只能查询文档中的单个字段:
export interface IKeyValue {
[property : string] : any ;
}
export interface IFilter {
[property : string] : IKeyValue;
}
const filter : IFilter = {
"Name" : { $eq : "Bob" }
}
我想要做的是允许IFilter
允许多个属性:
const filter : IFilter = {
"Name" : { $eq : "Bob" },
"Age" : { $gte : 21 }
}
如何创建一个允许多个动态键的 Typescript 接口,而无需恢复使用object
或any
作为IFilter
的类型?
我如何理解您的需求是:
首先让我们定义我们需要过滤的可能规则
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
用于数字以外的任何内容。
我想做的是让 IFilter 允许多个属性
IFilter
是一种具有string
索引签名的类型,并且已经允许具有string
名称类型和IKeyValue
值类型的多个属性。 只是 IDE/编译器不能协助自动完成,因为它不知道,由于可以添加属性的动态方式,里面是什么。
例如,您的代码甚至对未知的属性名称也有效:
const filterValue = filter["helloWorld"] // IKeyValue
const keyValue = filter["hello"]["World"] // any
我不确定,这里最好的解决方案是什么。 如果IFilter
有一组修复(可能是可选的)属性名称,例如Name
或Age
,则可以创建具有索引签名和已知属性的混合类型:
export interface IFilter {
[property: string]: IKeyValue | undefined;
Name?: IKeyValue;
Age?: IKeyValue;
}
const filter : IFilter = {
"Name": { $eq: "Bob" } // code assist for Name/Age properties
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.