为啥 react-map-gl Source 不使用对象?

Posted

技术标签:

【中文标题】为啥 react-map-gl Source 不使用对象?【英文标题】:Why is the react-map-gl Source not using an object?为什么 react-map-gl Source 不使用对象? 【发布时间】:2022-01-11 08:15:03 【问题描述】:

我正在尝试使用 typescript 将 geoJSON 添加到 react-map-gl 地图中

这是我的代码

<Source id="my-data" type="geojson" data=data>
    <Layer ...layerStyles/>
</Source>

data 变量是一个解析的 JSON 文件,所以它不是一个对象

我得到的错误是

 Overload 1 of 2, '(props: SourceProps | Readonly<SourceProps>): Source', gave the following error.
    Type 'object' is not assignable to type 'string | Feature<Geometry, GeoJsonProperties> | FeatureCollection<Geometry, GeoJsonProperties> | undefined'.
      Type '' is missing the following properties from type 'FeatureCollection<Geometry, GeoJsonProperties>': type, features
  Overload 2 of 2, '(props: SourceProps, context: any): Source', gave the following error.
    Type 'object' is not assignable to type 'string | Feature<Geometry, GeoJsonProperties> | FeatureCollection<Geometry, GeoJsonProperties> | undefined'.  TS2769

    123 |             onViewportChange=(nextView:typeof viewport) => setViewport(nextView)>
    124 |                 /* GeoJSON */
  > 125 |                 <Source id="my-data" type="geojson" data=data>
        |                                                     ^
    126 |                  <Layer ...layerStyles/>
    127 |                 </Source> 
    128 |                 markers

Source 组件中的数据 props 的类型应该是一个对象,如您从文档 https://visgl.github.io/react-map-gl/docs/api-reference/source 中看到的那样

如果您需要更多信息,请询问

【问题讨论】:

在这种情况下data 是什么? 这是一个 JSON 文件,包含我导入的所有 geoJSON 然后解析成一个对象,它是一个包含 geoJSON 的对象吗 当它到达此代码时,您是否验证了形状是正确的?显然Source 组件不同意并认为data 缺少名为typefeatures 的属性。 是的,数据既有类型又有特性,我可以对它们进行控制台记录。 你能在这里分享吗? 【参考方案1】:

说明

让我们分解这个错误:

Overload 1 of 2, '(props: SourceProps | Readonly<SourceProps>): Source'
...
Overload 2 of 2, '(props: SourceProps, context: any): Source

在顶层,它显示了您可以使用Source 组件的两种可能方式。假设您没有为它分配 context,让我们继续查看 Overload 1

Type 'object' is not assignable to type 'string | Feature<Geometry, GeoJsonProperties> | FeatureCollection<Geometry, GeoJsonProperties> | undefined'.

这告诉我们 typescript 认为 dataobject,但它期望它具体是 stringFeatureFeatureCollection(特别是 Geometry, GeoJsonProperties 的功能) 这告诉我们object 的具体类型不足以满足编译器的要求。

Type '' is missing the following properties from type 'FeatureCollection<Geometry, GeoJsonProperties>': type, features

它试图通过告诉我们object 类型中缺少的内容来提供帮助。请注意,它会将您的类型简化为没有属性的空对象。

解决方案

那么你如何告诉编译器 data 是什么? 我将假设您正在获取数据,因此打字稿无法自动推断其类型

选项 1 - 使用类型保护检查传入数据

function isFeatureCollection(data: unknown): data is FeatureCollection<Geometry, GeoJsonProperties> 
    return (
        typeof data === 'object'
        && data !== null
        && 'type' in data
        && 'features' in data
    );

然后使用类型保护退出渲染,打字稿将知道在此检查之后data将是Source所期望的类型

if (!isFeatureCollection(data)) return null;

<Source id="my-data" type="geojson" data=data>
    <Layer ...layerStyles/>
</Source>

选项 2 - 使用 as 将类型转换为您期望的类型:

const data = await getData() as FeatureCollection<Geometry, GeoJsonProperties>;

不建议这样做,因为您在这里丢弃了 Typescript 的类型保证

【讨论】:

以上是关于为啥 react-map-gl Source 不使用对象?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C++ 不使结构更紧密?

我可以像在(mapbox-gl-js 文档)中那样使用 react-map-gl 添加 GeoJSON 行吗?

为啥 TargetNullValue 更新可为空的 Source

为啥source命令无法使用

为啥每次进入命令都要重新source /etc/profile 才能生效

为啥#define _LARGEFILE_SOURCE 会破坏这些函数指针?