簡體   English   中英

在打字稿中合並類型(將鍵添加到現有的 keyof 類型)

[英]Merging types in typescript (adding keys to an existing keyof type)

如果我有一個由鍵組成的打字稿類型:

const anObject = {value1: '1', value2: '2', value3: '3'}
type objectKeys = keyof typeof anObject

然后我希望為該類型添加鍵,同時保留當前鍵,我該怎么做?
例如,如果我想將鍵“get_value1”、“get_value2”、“get_value3”添加到“objectKeys”類型

最后,我想要一個看起來像這樣的類型:

type objectKeys = keyof anObject + 'get_value1', 'get_value2', 'get_value3'

無需手動定義以“get_”為前綴的鍵,我知道我可以輸入鍵來創建這個對象——但這對我的用例來說是不可行的。 我只是想添加一些可能存在或可能不存在的鍵到類型“objectKeys”

我也知道我可以創建一個泛型或任何允許任何鍵值的類型,但是我必須知道實際的鍵名。 允許請求對象的任何鍵對我沒有幫助,我需要現有的鍵 + 我想添加的鍵。

感謝您的幫助。

為清楚起見添加:

const anObject = {val1: '1', val2: '2'}
type objectKeys = keyof typeof anObject

Object.keys(anObject).forEach(key => {
  const getAddition = `get_${key}`
  anObject[getAddition] = getAddition
})

// now I don't know whats next, how do I update objectKeys to include the 
// additions added in the forEach loop.

// What I really want is to not have to add the 'get' values to the object 
// at all, JUST to the type.  I want typechecking for the get values that 
// may or may not actually exist on the object.

希望那更清楚等等。

聽起來您要求串聯字符串文字類型:也就是說,您希望能夠采用字符串文字"get_"和另一個字符串文字,如"value1" ,並且讓 TypeScript 了解如果您將這些字符串串聯起來類型你得到一個類型為"get_value1"的字符串。 不幸的是,這個功能在 TypeScript 2.4 中不存在(並且可能在 2.5 或 2.6 中也不存在)🙁。

所以沒有辦法做你所要求的並保持嚴格的類型安全。 當然,您可以放寬類型安全並允許訪問任何未知密鑰:

const anObject = {val1: '1', val2: '2'};
const openObject: { [k: string]: any } & typeof anObject = anObject;
// replace "any" above with whatever type the get_XXX values are

Object.keys(openObject).forEach(key => {
  const getAddition = `get_${key}`
  openObject[getAddition] = getAddition
})
openObject.val1 = 1; // error, val1 is known to be a string
openObject.get_val1 = 1; // no error, get_val1 is any
openObject.gut_val4 = 1; // no error, oops, sorry

但你說你不想那樣做。


在這種情況下,我的建議是放棄向對象添加任意鍵,而是讓 getter(或任何它們)掛在單個get屬性上,如下所示:

const anObject = { val1: '1', val2: '2' }

type AnObject = typeof anObject;
type ObjectKeys = keyof AnObject;
type GetAugmentedObject = AnObject & { get: Record<ObjectKeys, any> }; 
// replace "any" above with whatever type the get.XXX values are 

const get = {} as GetAugmentedObject['get'];
Object.keys(anObject).forEach((key: ObjectKeys) => get[key] = key);
const augmentedObject: GetAugmentedObject = { ...anObject, get }

augmentedObject.val1; // ok
augmentedObject.val2; // ok 
augmentedObject.get.val1; // ok
augmentedObject.get.val2; // ok
augmentedObject.get.val3; // error, no val3
augmentedObject.git.val1; // error, no git

這對開發人員來說並沒有太大的不同( obj.get.val1obj.get_val1 ),但對 TypeScript 的跟進能力有很大的不同。 如果您對添加鍵的代碼有任何控制權,我強烈建議您像這樣做一些 TypeScript 友好的事情,因為如果您不需要的話,您不想花時間與 TypeScript 作斗爭。


否則,如果只有類型級別的字符串連接對你有用,並且你覺得你的用例足夠引人注目,也許你應該去相關的 GitHub 問題並給它一個 👍 並描述為什么它對你來說是必不可少的。

希望有幫助。 祝你好運!

2020 更新

它在打字稿v4.1.0 中

你可能需要這個 - https://github.com/microsoft/TypeScript/pull/40336

您可以使用模板文字。

這是一個示例,其中屬性id必須是# + key

interface MyInterface<K extends string> {
    something: {
        [key in K]: { id: `#${key}` }
    }
}

所以以下是正確的:

let x: MyInterface<'foo'> = {
    something: {
        foo: { id: '#foo' }
    }
}

但這是不正確的:

let y: MyInterface<'foo'> = {
    something: {
        foo: { id: 'foo' }
    }
}

暫無
暫無

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

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