Json TypeScript:将原始数据解析到接口中

Json TypeScript:将原始数据解析到接口中,json,typescript,Json,Typescript,在Typescript中(特别是使用钩子进行反应),我试图解析来自OAuth回调的一些URL哈希数据,并在我的组件中使用它 我可以通过调用window.location.hash const hash=window.location.hash.substr(1); const oauthData=hash.split(“&”) .map(v=>v.split('=')) .reduce((预[key,value])=>( key=='scope'?{…pre[key]:value.split(+

在Typescript中(特别是使用钩子进行反应),我试图解析来自OAuth回调的一些URL哈希数据,并在我的组件中使用它

我可以通过调用
window.location.hash

const hash=window.location.hash.substr(1);
const oauthData=hash.split(“&”)
.map(v=>v.split('='))
.reduce((预[key,value])=>(
key=='scope'?{…pre[key]:value.split(+')}:{…pre[key]:value}
), {});
{
“访问令牌”:“eyJhbGciOiJIUzI1NiJ9.EYJHDWQIIYMKWKILCJZWIIII1TKZCTFGILCJPC3MIOIJGY2NLC3NFDG9RZW4ILCJZY29WZXMIOIYC29JIHJJ3QGCNNLDCBYBG9JIHJ3ZWKMHYYJJJJJJJYYYYYYYJJJJ2ZLIIWIJJJJJJJJ0NTC4NTQYNZYZYZYKKKZYZYZYZLZYZYZYZYZYZYZLZYZYZYZYZYZYZYZYZYZYZYZYZYZYLZYZYLZYZYLZY,
“用户id”:“5NFBLX”,
“范围”:[
“心率”,
“营养”,
“地点”,
“睡眠”,
“活动”,
“重量”,
“社会的”,
“个人资料”,
“设置”
],
“令牌类型”:“承载者”,
“在中过期”:“343400”
}
太棒了!现在我想将所有这些信息传递到我的组件中,这就是事情变得有点混乱的地方,我无法找到将这些数据传递到我的组件中的方法,因为我破坏了类型安全性

我的组件是这样构建的

导出接口IOAuthProps{
accessToken:字符串
userID:string
范围:字符串[]
expiresIn:number
}
const OAuthFun:React.FC=(道具)=>{
const[ac]=useState(props.accessToken)
返回(
访问令牌={ac}
)
}
导出默认OAuthFun;
我已经尝试过类似的排列(为了简洁起见,我将省略其他属性):

非工作示例:甚至无法索引
oauthData
,因为它属于
{}


因为我甚至不能将原始json对象作为字典索引,所以我想我需要在构建的对象上创建一些类型安全性:

const oauthData=hash.split(“&”)
.map(v=>v.split('='))
.reduce((预[key,value])=>(
key=='scope'?{…pre[key]:value.split(+')}:{…pre[key]:value}
),{access_-token:String,user_-id:String,scope:[],expires_-in:Number});
但是,这破坏了reduce调用中的表达式:
没有重载与此调用匹配。
这让我相信我需要更简洁的方法来解析原始数据,但我真的不确定如何做到这一点

我想我可以直接将它从原始数据转换到接口,但是原始数据的命名约定使用下划线而不是camelcasting。另外,如果我改变了大小写,而不是学习如何规范化数据,它只是回避了问题,而没有解决它


将原始数据直接输入接口的正确方法是什么?

根据这些评论,我能够拼凑出这个解决方案

从“React”导入React;
导出接口IOAuthProps{
accessToken:字符串
userID:string
范围:字符串[]
expiresIn:number
}
导出函数ParseOAuthProperties(rawHashProperties:string):IOAuthProps{
const rawData=rawHashProperties.substr(1)
.split(“&”)
.map(v=>v.split('='))
.reduce((预[key,value])=>(
{…pre,[键]:值}
),{access_token:,user_id:,scope:,expires_in::});
常量normalizedData:IOAuthProps={
accessToken:rawData.access\u令牌,
userID:rawData.user\u id,
作用域:rawData.scope.split(+),
expiresIn:Number(rawData.expires\u in),
}
返回标准化数据;
}
const OAuthFun:React.FC=(道具)=>{
返回(
访问令牌={props.accessToken}
用户id={props.userID}
scope={props.scope}
expires in={props.expiresIn}
)
}
导出默认OAuthFun;
现在我可以使用我的方法,它封装了规范化并返回接口,然后从父组件使用它:

从“React”导入React;
从“/OAuthFun”导入OAuthFun,{ParseOAuthProperties,IOAuthProps}
常量应用程序:React.FC=()=>{
const props:IOAuthProps=ParseOAuthProperties(window.location.hash)
返回(
{/*注意,您可以使用spread运算符*/}传递接口
);
}
导出默认应用程序;

正确的方法是让接口声明描述从服务器返回的数据。这意味着它需要具有相同的属性名称。如果需要属性名称规范化,则应在服务器上执行。记住,接口声明只描述数据的形状。接口没有任何运行时行为。他们只是描述shapes@AluanHaddad我会在服务器端对其进行规范化,但我与之交互的不是我的服务。实际上是菲比特的。不幸的是,我无法将属性发送到我自己的服务器(我首先尝试了),因为散列参数没有转发,必须首先在前端处理(这将我们带到这里),我理解。因此,您需要命名typescript接口的属性,以正确反映数据的形状。这意味着使用数据源使用的任何命名约定。我同意在你可以避免的情况下这样做是不可取的,因为习惯用语并遵循语言惯例(如驼峰式的外壳)是很好的,但听起来你并没有choice@AluanHaddad啊,好吧,我明白了!我将发布我的解决方案,我可以按照您描述的方式解析数据,并对其进行规范化,以符合我的项目约定。非常感谢。