簡體   English   中英

打字稿:通過添加具有特定命名的新字段來動態擴展界面

[英]Typescript: Extend interface dynamically by adding new fields with certain naming

我有一個這樣的界面:

interface ProjectCostData {
  purchasePrice: number;
  propertyValue: number;
  recentlyDamaged: boolean;
}

現在我想根據上面的接口動態創建一個這樣的接口:

interface ProjectCostDataWithSetters {
  purchasePrice: number;
  setPurchasePrice: Dispatch<SetStateAction<number>>;
  propertyValue: number;
  setPropertyValue: Dispatch<SetStateAction<number>>;
  recentlyDamaged: boolean;
  setRecentlyDamage: Dispatch<SetStateAction<boolean>>;
}

--> 映射第一個接口,並為每個條目 A 添加一個新條目 B,其鍵為 `set${entryKey}` 和可以從條目 A 派生的類型。

這在 TS 中可能嗎?

背景:我有一個基於 OpenAPI 的后端,它為我提供 API 結構作為.yaml文件。 我通過生成器傳遞該文件並接收接口和函數以與 API 對話。 在前端,我使用 react 上下文來構建全局狀態。 我想根據生成器的輸出構建我的全局反應上下文。

在打字稿 4.0 或更早版本中,這是不可能的。 字符串,包括屬性名稱,要么完全稱為常量(即"foo" )、一組有限可能性的常量之一(即"foo" | "bar" ),或者只是具有任何內容的任何字符串( string )。 因此,您不能根據其他屬性名稱構造新的屬性名稱。


然而,Typescript 4.1(目前是測試版)有一些特性可能對模板文字類型有幫助

interface ProjectCostData {
  purchasePrice: number;
  propertyValue: number;
  recentlyDamaged: boolean;
}

// Create a new setter property for each key of an interface
type WithSetters<T extends { [k: string]: any }> = T & {
    [K in keyof T & string as `set_${K}`]: (newValue: T[K]) => void
}

// Testing
declare const obj: WithSetters<ProjectCostData>
obj.purchasePrice // number
obj.set_purchasePrice(123) // (newValue: number) => void

操場

那:

[K in keyof T & string as `set_${K}`]

有點時髦。 這個 PR 比我能更好地解釋這一點。


您甚至可以處理大小寫變化:

interface Capitals { a: 'A', b: 'B', c: 'C' /* ... */, p: 'P' }

type Capitalize<T extends string> =
    T extends `${infer First}${infer Rest}`
        ? First extends keyof Capitals
            ? `${Capitals[First]}${Rest}`
            : T
        : T


type SetterName<T extends string> = `set${Capitalize<T>}`

type SetPropName = SetterName<'propName'> // type: "setPropName"

操場

將所有這些放在一起有點棘手,尤其是在測試版中。 但我認為,從理論上講,實現這種類型轉換的所有部分都存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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