Leaflet 1.6.0结合TypeScript扩展GeoJSON组件报ts2554错误
报错核心原因
- TypeScript无法识别你通过
L.GeoJSON.extend生成的构造函数的入参类型,默认会认为该构造函数不需要传参,因此触发Expected 0 arguments, but got 1.ts(2554)类型错误。 - 你重写了
initialize初始化方法,但没有调用父类L.GeoJSON的原生初始化逻辑,会导致原生GeoJSON的加载、渲染能力完全失效,且入参格式不符合Leaflet类的规范。 - 你当前写的是React函数组件,直接返回Leaflet类实例属于无效用法,react-leaflet框架下的组件需要返回JSX元素,或者手动将生成的图层挂载到地图实例上。
最优解决方法(无需手动扩展原生类)
如果你只是需要自定义onEachFeature、pointToLayer、style配置,直接使用react-leaflet封装好的GeoJSON组件传参即可,完全不需要自己扩展原生类:
import React, { useContext } from 'react'; import { GeoJSON } from "react-leaflet"; import uuid from "react-uuid"; import L from 'leaflet'; import { BoundaryMarkContext } from '../MapsPage'; import { getStyle} from '../../style'; type Props = { featureCollection: GeoJSON.FeatureCollection; }; const CustomGeoJson = (props: Props) => { const keyForFeatureCollection = uuid(); const boundaryMarkChangeDetails = useContext(BoundaryMarkContext); const onEachFeature = (feature: GeoJSON.Feature, layer: L.Layer) => { layer.on('click', (e) => { boundaryMarkChangeDetails.handleBoundaryMarkClick(e) }); } const boundaryMarkPointToLayer = (feature: GeoJSON.Feature, latlng: L.LatLng) => { // 补全你的点图层渲染逻辑,示例为返回圆形标记 return L.circleMarker(latlng, { radius: 5, fillColor: '#ff0000' }) }; return <GeoJSON key={keyForFeatureCollection} data={props.featureCollection} onEachFeature={onEachFeature} pointToLayer={boundaryMarkPointToLayer} style={getStyle} /> }; export default CustomGeoJson;
如果你确实需要扩展原生L.GeoJSON类
如果有自定义属性、自定义方法的扩展需求,按照以下方式修改即可解决类型报错和逻辑问题:
import React, { useContext, useEffect } from 'react'; import { useLeaflet } from "react-leaflet"; import L from 'leaflet'; import uuid from "react-uuid"; import { BoundaryMarkContext } from '../MapsPage'; import { getStyle} from '../../style'; type Props = { featureCollection: GeoJSON.FeatureCollection; }; // 1. 先定义扩展类的类型,解决TypeScript参数报错问题 interface CustomGeoJSON extends L.GeoJSON { data: GeoJSON.FeatureCollection; customKey: string; } interface CustomGeoJSONOptions extends L.GeoJSONOptions { customKey?: string; } // 2. 正确扩展L.GeoJSON类,调用父类初始化方法 const CustomGeoJSONClass = L.Class.extend<new (geojson: GeoJSON.FeatureCollection, options?: CustomGeoJSONOptions) => CustomGeoJSON>(L.GeoJSON, { initialize: function (geojson: GeoJSON.FeatureCollection, options?: CustomGeoJSONOptions) { // 先调用父类原生初始化逻辑,必须写 L.GeoJSON.prototype.initialize.call(this, geojson, options); // 赋值自定义属性 this.data = geojson; this.customKey = options?.customKey || ''; }, // 可以在这里加你需要的自定义方法 customMethod() { console.log('自定义方法执行', this.customKey) } }); const CustomGeoJson = (props: Props) => { const { map } = useLeaflet(); const keyForFeatureCollection = uuid(); const boundaryMarkChangeDetails = useContext(BoundaryMarkContext); // 3. 组件挂载时加载图层,卸载时移除图层 useEffect(() => { const onEachFeature = (feature: GeoJSON.Feature, layer: L.Layer) => { layer.on('click', (e) => { boundaryMarkChangeDetails.handleBoundaryMarkClick(e) }); } const boundaryMarkPointToLayer = (feature: GeoJSON.Feature, latlng: L.LatLng) => { return L.circleMarker(latlng, { radius: 5 }) }; // 实例化自定义GeoJSON类,参数顺序为【数据,配置项】,符合Leaflet规范 const geoJsonInstance = new CustomGeoJSONClass(props.featureCollection, { customKey: keyForFeatureCollection, onEachFeature, pointToLayer: boundaryMarkPointToLayer, style: getStyle }); // 把图层加到地图上 map.addLayer(geoJsonInstance); // 组件卸载时清除图层,避免内存泄漏 return () => { map.removeLayer(geoJsonInstance); } }, [map, props.featureCollection, boundaryMarkChangeDetails]) return null; }; export default CustomGeoJson;
内容的提问来源于stack exchange,提问作者Rayan
相关产品推荐
相关产品推荐

