如何使用 reason-react 在函数签名中定义接受多种类型的绑定?
How to define a binding that accepts multiple types in the function signature using reason-react?
在定义 reason-react 绑定时,我想知道如何确定接受多种类型的绑定。例如,我有一个参数 ~value
应该接受:string
、number
、array(string)
或 array(number)
。目前我正在使用 option('a)
但我认为这不是最干净的方法,因为我更愿意明确定义类型。如何才能做到这一点?我看过 bs.unwrap
但我不确定如何将外部语法组合到函数签名中。
module Select = {
[@bs.module "material-ui/Select"] external reactClass : ReasonReact.reactClass = "default";
let make =
(
...
~menuProps: option(Js.t({..}))=?,
~value: option('a), /* Should be type to string, number, Array of string and Array of number */
~style: option(ReactDOMRe.style)=?,
...
children
) =>
ReasonReact.wrapJsForReason(
~reactClass,
~props=
Js.Nullable.(
{
...
"value": from_opt(value),
"style": from_opt(style)
}
),
children
);
};
作为附带问题,由于数字类型未定义,我的绑定是否也必须将浮点数和整数映射到数字?
这可以通过使用以下内容(受 https://github.com/astrada/reason-react-toolbox/ 启发)实现。
type jsUnsafe;
external toJsUnsafe : 'a => jsUnsafe = "%identity";
let unwrapValue =
(r: [< | `Int(int) | `IntArray(array(int)) | `String(string) | `StringArray(array(string))]) =>
switch r {
| `String(s) => toJsUnsafe(s)
| `Int(i) => toJsUnsafe(i)
| `StringArray(a) => toJsUnsafe(a)
| `IntArray(a) => toJsUnsafe(a)
};
let optionMap = (fn, option) =>
switch option {
| Some(value) => Some(fn(value))
| None => None
};
module Select = {
[@bs.module "material-ui/Select"] external reactClass : ReasonReact.reactClass = "default";
let make =
(
...
~menuProps: option(Js.t({..}))=?,
~value:
option(
[ | `Int(int) | `IntArray(array(int)) | `String(string) | `StringArray(array(string))]
)=?,
~style: option(ReactDOMRe.style)=?,
...
children
) =>
ReasonReact.wrapJsForReason(
~reactClass,
~props=
Js.Nullable.(
{
...
"value": from_opt(optionMap(unwrapValue, value)),
"style": from_opt(style)
}
),
children
);
};
可以通过以下方式使用;
<Select value=(`IntArray([|10, 20|])) />
<Select value=(`Int(10)) />
我从 reason-react-toolbox 复制了 toJsUnsafe
,所以我不完全确定它到底做了什么,当我发现时我会更新我的答案。
unwrapValue
函数接受一个可以是所列类型之一的值,并将其转换为 jsUnsafe。
unwrapValue
的类型允许列出的任何变体,但也允许其中的一个子集,例如。 (这是启用此功能的变体之前的 <
)。
let option = (value: option([ | `String(string) | `Int(int)])) =>
Js.Nullable.from_opt(option_map(unwrapValue, value));
只是添加到@InsidersByte 的回答中,因为这个问题不是特定于原因反应的,可以概括:
module Value = {
type t;
external int : int => t = "%identity";
external intArray : array(int) => t = "%identity";
external string : string => t = "%identity";
external stringArray : array(string) => t = "%identity";
};
let values : list(Value.t) = [
Value.int(4),
Value.stringArray([|"foo", "bar"|])
];
此解决方案在 Value
模块中也是自包含的,与 JavaScript 等价物相比不会产生任何开销,因为 "%identity"
外部是经过优化的空操作。
在定义 reason-react 绑定时,我想知道如何确定接受多种类型的绑定。例如,我有一个参数 ~value
应该接受:string
、number
、array(string)
或 array(number)
。目前我正在使用 option('a)
但我认为这不是最干净的方法,因为我更愿意明确定义类型。如何才能做到这一点?我看过 bs.unwrap
但我不确定如何将外部语法组合到函数签名中。
module Select = {
[@bs.module "material-ui/Select"] external reactClass : ReasonReact.reactClass = "default";
let make =
(
...
~menuProps: option(Js.t({..}))=?,
~value: option('a), /* Should be type to string, number, Array of string and Array of number */
~style: option(ReactDOMRe.style)=?,
...
children
) =>
ReasonReact.wrapJsForReason(
~reactClass,
~props=
Js.Nullable.(
{
...
"value": from_opt(value),
"style": from_opt(style)
}
),
children
);
};
作为附带问题,由于数字类型未定义,我的绑定是否也必须将浮点数和整数映射到数字?
这可以通过使用以下内容(受 https://github.com/astrada/reason-react-toolbox/ 启发)实现。
type jsUnsafe;
external toJsUnsafe : 'a => jsUnsafe = "%identity";
let unwrapValue =
(r: [< | `Int(int) | `IntArray(array(int)) | `String(string) | `StringArray(array(string))]) =>
switch r {
| `String(s) => toJsUnsafe(s)
| `Int(i) => toJsUnsafe(i)
| `StringArray(a) => toJsUnsafe(a)
| `IntArray(a) => toJsUnsafe(a)
};
let optionMap = (fn, option) =>
switch option {
| Some(value) => Some(fn(value))
| None => None
};
module Select = {
[@bs.module "material-ui/Select"] external reactClass : ReasonReact.reactClass = "default";
let make =
(
...
~menuProps: option(Js.t({..}))=?,
~value:
option(
[ | `Int(int) | `IntArray(array(int)) | `String(string) | `StringArray(array(string))]
)=?,
~style: option(ReactDOMRe.style)=?,
...
children
) =>
ReasonReact.wrapJsForReason(
~reactClass,
~props=
Js.Nullable.(
{
...
"value": from_opt(optionMap(unwrapValue, value)),
"style": from_opt(style)
}
),
children
);
};
可以通过以下方式使用;
<Select value=(`IntArray([|10, 20|])) />
<Select value=(`Int(10)) />
我从 reason-react-toolbox 复制了 toJsUnsafe
,所以我不完全确定它到底做了什么,当我发现时我会更新我的答案。
unwrapValue
函数接受一个可以是所列类型之一的值,并将其转换为 jsUnsafe。
unwrapValue
的类型允许列出的任何变体,但也允许其中的一个子集,例如。 (这是启用此功能的变体之前的 <
)。
let option = (value: option([ | `String(string) | `Int(int)])) =>
Js.Nullable.from_opt(option_map(unwrapValue, value));
只是添加到@InsidersByte 的回答中,因为这个问题不是特定于原因反应的,可以概括:
module Value = {
type t;
external int : int => t = "%identity";
external intArray : array(int) => t = "%identity";
external string : string => t = "%identity";
external stringArray : array(string) => t = "%identity";
};
let values : list(Value.t) = [
Value.int(4),
Value.stringArray([|"foo", "bar"|])
];
此解决方案在 Value
模块中也是自包含的,与 JavaScript 等价物相比不会产生任何开销,因为 "%identity"
外部是经过优化的空操作。