在typescript中有没有一种方法可以声明类似“quot;嵌套对象“中的字符串”;?
我有这个用例。我有一个生成的常量,它复制了JSON对象结构: 例如: JSON 生成常量:在typescript中有没有一种方法可以声明类似“quot;嵌套对象“中的字符串”;?,typescript,Typescript,我有这个用例。我有一个生成的常量,它复制了JSON对象结构: 例如: JSON 生成常量: const MyConst = { first: 'first', second: { this: 'second.this', a: 'second.a', object: { and : 'second.object.and', } } } 它用于将对象映射到一个种类安全的结构,这样我就可以调用getInfoFrom
const MyConst = {
first: 'first',
second: {
this: 'second.this',
a: 'second.a',
object: {
and : 'second.object.and',
}
}
}
它用于将对象映射到一个种类安全的结构,这样我就可以调用getInfoFromJson(MyConst.second.a)
,并将complex
作为返回,当JSON数据(它是一个静态文件)获得更多密钥时,它会通过脚本进行更新
现在,getInfoFromJson
的函数签名是
function getInfoFromJson(path: string): string {}
我想说的是“将任何字符串作为参数,只要它包含在MyConst中”
我还没有找到怎么做,我搜索的内容看起来不可能,但我想我可以试一试并在这里提问。首先让我们假设
MyConst
的强类型足以让编译器知道它包含的确切字符串值。要做到这一点,最简单的方法是使用以下命令定义它:
如果检查其类型,您将看到:
/* const MyConst: {
readonly first: "first";
readonly second: {
readonly this: "second.this";
readonly a: "second.a";
readonly object: {
readonly and: "second.object.and";
};
};
} */
现在您需要一个名为
NestedValsMatching
的类型函数,其中给定类型T
和V
,您将得到T
中所有值的并集,无论嵌套得有多深,匹配的V
。因此理想情况下,NestedValsMatching
将为您提供联合“first”|“second.a”|“second.a”|“second.object.and”
NestedValsMatching
最直接的实现方式是递归的,而TypeScript目前不支持这种方式(请参阅)。编译器实际上不会抱怨它,但它确实会导致一些糟糕的性能和其他奇怪之处。在这里(但不要使用它)
/首先,让我们假设MyConst
的强类型足以让编译器知道它包含的确切字符串值。要做到这一点,最简单的方法是使用以下命令定义它:
如果检查其类型,您将看到:
/* const MyConst: {
readonly first: "first";
readonly second: {
readonly this: "second.this";
readonly a: "second.a";
readonly object: {
readonly and: "second.object.and";
};
};
} */
现在您需要一个名为NestedValsMatching
的类型函数,其中给定类型T
和V
,您将得到T
中所有值的并集,无论嵌套得有多深,匹配的V
。因此理想情况下,NestedValsMatching
将为您提供联合“first”|“second.a”|“second.a”|“second.object.and”
NestedValsMatching
最直接的实现方式是递归的,而TypeScript目前不支持这种方式(请参阅)。编译器实际上不会抱怨它,但它确实会导致一些糟糕的性能和其他奇怪之处。在这里(但不要使用它)
/假设我们能够构造如下类型:
类型对={
‘第一’:‘我只是第一’,
'第二,这个':'是',
“second.a”:“complex”,
'second.object.and':'里面可能有更多的对象'
}
在这种情况下,我们可以使用像'second.a'
这样的字符串文本类型来查找字符串文本类型'complex'
事实证明,您可以构造足够接近的对象,使其成为有用的对。本质上,给定具有相同内部结构的两种类型S
和T
(即,它们具有相同的属性,如果这些属性的值是对象,则它们递归地具有相同的内部结构),我们希望将S
的“叶”属性与T
的“叶”属性配对
我的解决方案如下。正如@jcalz在他的回答中指出的,这是一个递归定义的映射类型,所以这里是龙
type Pairs=S扩展属性key?记录:{
[K in keyof S和keyof T]:成对
}[科学和技术的关键]
类型Lookup=P扩展记录?U:从来没有
键入PairsKeys=P扩展记录?K:从来没有
Pairs
类型实际上构造了一个类似于Record | Record |…
的联合类型,因此需要查找
类型来执行从second.a'
到complex'
的实际映射。需要使用PairsKeys
类型来构造键的类型,以便拒绝无效键。但它确实有效:
型式试验=成对
函数查找(键:K):查找{
抛出错误();//此处未实现
}
//推断出一种“情结”
设a=lookup('second.a');
//“second.b”上的类型错误
设b=lookup('second.b');
所有这些都说明了,既然反正生成了MyConst
,也许您也有办法将原始对作为常量生成?这似乎应该是一个更好的解决方案
假设我们能够构造如下类型:
类型对={
‘第一’:‘我只是第一’,
'第二,这个':'是',
“second.a”:“complex”,
'second.object.and':'里面可能有更多的对象'
}
在这种情况下,我们可以使用像'second.a'
这样的字符串文本类型来查找字符串文本类型'complex'
事实证明,您可以构造足够接近的对象,使其成为有用的对。本质上,给定具有相同内部结构的两种类型S
和T
(即,它们具有相同的属性,如果这些属性的值是对象,则它们递归地具有相同的内部结构),我们希望将S
的“叶”属性与T
的“叶”属性配对
我的解决方案如下。正如@jcalz在他的回答中指出的,这是一个递归定义的映射类型,所以这里是龙
type Pairs=S扩展属性key?记录:{
[K in keyof S和keyof T]:成对
}[科学和技术的关键]
类型Lookup=P扩展记录?U:从来没有
键入PairsKeys=P扩展记录?K:从来没有
Pairs
类型实际上构造了一个类似于Record | Record |…
的联合类型,因此需要Lookup
类型来执行
/* const MyConst: {
readonly first: "first";
readonly second: {
readonly this: "second.this";
readonly a: "second.a";
readonly object: {
readonly and: "second.object.and";
};
};
} */
// Suppose we are able to construct a type like this:
type Pairs = {
'first': 'I am just first',
'second.this': 'is',
'second.a': 'complex',
'second.object.and': 'It could have more objects inside'
}