簡體   English   中英

帶有多個動態鍵的 Typescript 接口

[英]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 接口,而無需恢復使用objectany作為IFilter的類型?

我如何理解您的需求是:

  • 你有一些實體,比方說用戶
  • 你想創建一個通用的 Filter 類型,它可以用於不同的實體
  • 通用過濾器類型對於每個實體都應該是類型安全的

首先讓我們定義我們需要過濾的可能規則

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有一組修復(可能是可選的)屬性名稱,例如NameAge ,則可以創建具有索引簽名和已知屬性的混合類型:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM