Rescript 对 React Native 的支持还算可以,但如今的 RN 已经是 Expo 的 RN 了,所以仍然有些落后,在这个 template 中,我测试了 rescript + rescript-react-native + expo + nativewind 的组合,可以跑起来:

其中有两个问题,一是 rescript-expo 对 rescript v11 的兼容性,我通过简单的注释让其通过编译:

二是对于 nativewind 的支持,编写的 binding 非常丑陋:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type default_style = {
className?: string,
children?: React.element,
}

@module("nativewind")
external styled: React.component<'a> => React.component<default_style> = "styled"

module StyledText = {
let make = styled(ReactNative.Text.make)
}

module StyledView = {
let make = styled(ReactNative.View.make)
}

module StyledImage = {
type props = {
source?: string,
...default_style,
}

@module("nativewind")
external styled: React.component<'a> => React.component<props> = "styled"

let make: React.component<props> = styled(ReactNative.Image.make)
}

而这似乎并没有好的解决方案,理想中的实现应该是:

1
2
3
4
5
6
7
8
9
10
11
12
13
module Styled = (Component: {
type params // or type params = 'a
let make: React.component<props>
}) => {
type props = {
...Component.props, // This can't work as it is not defined as record
className?: string
}
@module("nativewind")
external styled: React.component<Component.props> => React.component<props> = "styled"

let make: React.component<props> = styled(Component.make)
}

或者退一步:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type styledProps = {
className?: string,
// ...
}

@module("nativewind")
external styled: React.component<'a> => React.component<'b> = "styled"

module StyledText = {
type props = {
...ReactNative.Text.props,
...styledProps
}

let make: React.component<props> = styled(ReactNative.Text.make)
}

但这在当前的 rescript 中,根本无法实现。

详细的讨论看这个帖子: