2017-08-31 62 views
1

如果我有一个打字稿类型由密钥:在打字稿合并类型(添加键现有keyof型)

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. 

希望这就是clearerer和这样。

+1

据我读的keyof和映射类型的规范,是没有办法做到这一点。希望我错了,但转换关键名称并不是我见过的打字稿团队演示的一个功能。 –

回答

1

这听起来像你问concatenation of string literal types:那就是,你要能够把字符串文字"get_"和另一个字符串字面像"value1",并有打字稿明白,如果您连接这些类型的字符串你得到一个字符串"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 

但你说你不想这样做。


在这种情况下,我会做的建议是放弃将任意键的对象,而是使吸气剂(或不管他们是)挂落单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作斗争。


否则,如果在类型级别唯一字符串连接会为你工作,你觉得你的使用情况是足够的吸引力,也许你应该去the relevant GitHub issue并给它一个并说明为什么它是一个必须具备的为你。

希望有所帮助。祝你好运!

+0

非常感谢jcalz,很好的回答!您使用单个get属性的方法将完美工作 – laramie