如何为 Js.Dict.get 使用 Js.Dict.t 类型
How to use Js.Dict.t type for Js.Dict.get
我正在尝试将一些 JS 转换为 Reason,在此过程中我需要键入 JSON 响应并检查对象中是否存在键。
这是我当前的代码:
let api_key = "";
let api_url = "http://ws.audioscrobbler.com/2.0";
let method = "user.getRecentTracks";
let user = "montogeek";
type trackAttr = {
nowplaying: bool
};
type artistT = {
text: string
}
type trackT = {
attr: trackAttr,
name: string,
artist: artistT
};
type recentTrackT = {
track: array(Js.Dict.t(trackT))
};
type response = {
recenttracks: recentTrackT
};
Js.Promise.(Fetch.fetch(api_url ++ "?method=" ++ method ++ "&" ++ user ++ "=" ++ user ++ "&limit=1&format=json&api_key=" ++ api_key)
|> then_(Fetch.Response.json)
|> then_(json: response => {
let lasttrack = json.recenttracks.track[0];
let online = switch (Js.Dict.get(lasttrack, "attr")) {
| None => false
| Some(track) => track.attr.nowplaying
};
let info = online ? "Enjoying" ++ lasttrack.name ++ "by " ++ lasttrack.artist["#text"] ++ "}" : "";
{ online, info }
}));
目前我收到这个错误:
We've found a bug for you!
/Users/montogeek/Infinite/Lov/online/src/lastfm.re 37:41-49
35 ┆ | Some(track) => track.attr.nowplaying
36 ┆ };
37 ┆ let info = online ? "Enjoying" ++ lasttrack.name ++ "by " ++ lasttrack
.artist["#text"] ++ "}" : "";
38 ┆
39 ┆ { online, info }
This has type:
Js.Dict.t(trackT) (defined as Js.Dict.t(trackT))
But somewhere wanted:
trackT
我无法删除 Js.Dict.t
类型,因为 Js.Dict.get
不喜欢它。
我怎样才能输入回复才能生效?
谢谢!
您可能想尝试以较小的增量构建它,因为您已经在这里给自己挖了一个很深的坑。
首先,您是根据记录类型而不是 JS 对象类型来描述您的 JSON 响应。
这是一个记录类型:
type t = { foo: string };
这是一个 JS 对象类型:
type t = {. "foo": string };
一个细微但非常重要的区别。
其次 Js.Dict.t(trackT)
不是你想的那样(尽管我也不清楚那到底是什么)。它描述了一个用作散列的 JS 对象,具有 String
类型的键和 trackT
类型的值。这看起来像是在尝试解决第一个问题,但只会让漏洞变得更深,所以也许只是恢复它。
第三,您不能仅通过注释来断言 JSON 响应具有 response
类型。这是一个健全的类型系统,它只会给你一个类型错误。如果你想绕过类型系统(这几乎总是一个坏主意)你必须更加明确。
还有一些其他小错误,但这超出了本文的范围。
所以你应该做的是以下两件事之一:
正确的方法 是使用 bs-json 之类的库将 JSON 响应解码为您已经定义的记录类型,验证在应该做的边界处的数据形状,然后继续像往常一样使用记录类型:
/* assume record types are defined above */
module Decode = {
open Json.Decode;
let trackAttr = json => {
nowplaying: json |> field("nowplaying", bool)
};
let artist = json => {
text: json |> field("text", string)
}
let track = json => {
attr: json |> optional(field("attr", trackAttr)),
name: json |> field("name", string),
artist: json |> field("artist", artist)
};
let recentTrack = json => {
track: json |> field("track", array(track))
};
let response = json => {
recenttracks: json |> field("recenttracks", recentTrack)
};
};
Js.Promise.(Fetch.fetch(api_url ++ "?method=" ++ method ++ "&" ++ user ++ "=" ++ user ++ "&limit=1&format=json&api_key=" ++ api_key)
|> then_(Fetch.Response.json)
|> then_(json => {
let response = Decode.response(json);
let lasttrack = response.recenttracks.track[0];
...
}));
快速而肮脏的方法是将记录类型转换为JS对象类型,然后断言数据具有该形状,从而绕过类型系统。如果它没有您期望的形状,您可能会在任何地方遇到运行时错误,并且需要手动追踪问题的根源。这可能是这样的:
type trackAttr = {.
"nowplaying": bool
};
type artistT = {.
"text": string
}
type trackT = {.
"attr": trackAttr,
"name": string,
"artist": artistT
};
type recentTrackT = {.
"track": array(trackT)
};
type response = {.
"recenttracks": recentTrackT
};
external unsafeCastJsonAsResponse : Js.Json.t => response = "%identity";
Js.Promise.(Fetch.fetch(api_url ++ "?method=" ++ method ++ "&" ++ user ++ "=" ++ user ++ "&limit=1&format=json&api_key=" ++ api_key)
|> then_(Fetch.Response.json)
|> then_(json => {
let response = unsafeCastJsonAsResponse(json);
let lasttrack = response##recenttracks##track[0];
...
}));
我正在尝试将一些 JS 转换为 Reason,在此过程中我需要键入 JSON 响应并检查对象中是否存在键。
这是我当前的代码:
let api_key = "";
let api_url = "http://ws.audioscrobbler.com/2.0";
let method = "user.getRecentTracks";
let user = "montogeek";
type trackAttr = {
nowplaying: bool
};
type artistT = {
text: string
}
type trackT = {
attr: trackAttr,
name: string,
artist: artistT
};
type recentTrackT = {
track: array(Js.Dict.t(trackT))
};
type response = {
recenttracks: recentTrackT
};
Js.Promise.(Fetch.fetch(api_url ++ "?method=" ++ method ++ "&" ++ user ++ "=" ++ user ++ "&limit=1&format=json&api_key=" ++ api_key)
|> then_(Fetch.Response.json)
|> then_(json: response => {
let lasttrack = json.recenttracks.track[0];
let online = switch (Js.Dict.get(lasttrack, "attr")) {
| None => false
| Some(track) => track.attr.nowplaying
};
let info = online ? "Enjoying" ++ lasttrack.name ++ "by " ++ lasttrack.artist["#text"] ++ "}" : "";
{ online, info }
}));
目前我收到这个错误:
We've found a bug for you!
/Users/montogeek/Infinite/Lov/online/src/lastfm.re 37:41-49
35 ┆ | Some(track) => track.attr.nowplaying
36 ┆ };
37 ┆ let info = online ? "Enjoying" ++ lasttrack.name ++ "by " ++ lasttrack
.artist["#text"] ++ "}" : "";
38 ┆
39 ┆ { online, info }
This has type:
Js.Dict.t(trackT) (defined as Js.Dict.t(trackT))
But somewhere wanted:
trackT
我无法删除 Js.Dict.t
类型,因为 Js.Dict.get
不喜欢它。
我怎样才能输入回复才能生效?
谢谢!
您可能想尝试以较小的增量构建它,因为您已经在这里给自己挖了一个很深的坑。
首先,您是根据记录类型而不是 JS 对象类型来描述您的 JSON 响应。
这是一个记录类型:
type t = { foo: string };
这是一个 JS 对象类型:
type t = {. "foo": string };
一个细微但非常重要的区别。
其次 Js.Dict.t(trackT)
不是你想的那样(尽管我也不清楚那到底是什么)。它描述了一个用作散列的 JS 对象,具有 String
类型的键和 trackT
类型的值。这看起来像是在尝试解决第一个问题,但只会让漏洞变得更深,所以也许只是恢复它。
第三,您不能仅通过注释来断言 JSON 响应具有 response
类型。这是一个健全的类型系统,它只会给你一个类型错误。如果你想绕过类型系统(这几乎总是一个坏主意)你必须更加明确。
还有一些其他小错误,但这超出了本文的范围。
所以你应该做的是以下两件事之一:
正确的方法 是使用 bs-json 之类的库将 JSON 响应解码为您已经定义的记录类型,验证在应该做的边界处的数据形状,然后继续像往常一样使用记录类型:
/* assume record types are defined above */
module Decode = {
open Json.Decode;
let trackAttr = json => {
nowplaying: json |> field("nowplaying", bool)
};
let artist = json => {
text: json |> field("text", string)
}
let track = json => {
attr: json |> optional(field("attr", trackAttr)),
name: json |> field("name", string),
artist: json |> field("artist", artist)
};
let recentTrack = json => {
track: json |> field("track", array(track))
};
let response = json => {
recenttracks: json |> field("recenttracks", recentTrack)
};
};
Js.Promise.(Fetch.fetch(api_url ++ "?method=" ++ method ++ "&" ++ user ++ "=" ++ user ++ "&limit=1&format=json&api_key=" ++ api_key)
|> then_(Fetch.Response.json)
|> then_(json => {
let response = Decode.response(json);
let lasttrack = response.recenttracks.track[0];
...
}));
快速而肮脏的方法是将记录类型转换为JS对象类型,然后断言数据具有该形状,从而绕过类型系统。如果它没有您期望的形状,您可能会在任何地方遇到运行时错误,并且需要手动追踪问题的根源。这可能是这样的:
type trackAttr = {.
"nowplaying": bool
};
type artistT = {.
"text": string
}
type trackT = {.
"attr": trackAttr,
"name": string,
"artist": artistT
};
type recentTrackT = {.
"track": array(trackT)
};
type response = {.
"recenttracks": recentTrackT
};
external unsafeCastJsonAsResponse : Js.Json.t => response = "%identity";
Js.Promise.(Fetch.fetch(api_url ++ "?method=" ++ method ++ "&" ++ user ++ "=" ++ user ++ "&limit=1&format=json&api_key=" ++ api_key)
|> then_(Fetch.Response.json)
|> then_(json => {
let response = unsafeCastJsonAsResponse(json);
let lasttrack = response##recenttracks##track[0];
...
}));