如果我有一个由键组成的打字稿类型:
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 _'的键,我知道我可以键入键来创建此对象 - 但这对我的用例来说是不可行的。我只是想添加一些可能存在或可能不存在的键,对象键'
我也知道我可以创建一个允许任何键值的泛型或任何类型,但是我必须知道实际的键名。我无法允许任何键被请求对象,我需要现有的键+我想要添加的键。
感谢您的帮助。
为了清晰起见而添加:
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.
希望那个清理工具等。
答案 0 :(得分:1)
听起来你要求concatenation of string literal types:也就是说,你希望能够获取字符串文字"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.val1
与obj.get_val1
),情况并无太大差异,但对TypeScript的跟进能力有很大影响。如果你对添加键的代码有任何控制权,我强烈建议你做一些类似于TypeScript的事情,因为你不想花时间与TypeScript战斗,如果你不需要的话。
否则,如果只有类型级别的字符串连接对您有用,并且您觉得您的用例足够引人注目,那么您应该去the relevant GitHub issue并给它一个并描述为什么它是必须的对你而言。
希望有所帮助。祝你好运!
答案 1 :(得分:1)
答案 2 :(得分:0)
您可以使用模板文字。
以下是属性 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' }
}
}