質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

2959閲覧

react-leaflet のtypescriptへの対応 (Interfaceの取り扱い)

IsoNi

総合スコア32

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2021/05/05 06:10

編集2021/05/06 00:42

React-leafletというライブラリのJavascriptの使用例のところをTypescriptに書き換えようとしていますが、Interfaceの取り扱いのところで引っかかってます。

内容は右上に小さなマップを追加しようというもので、ソースのURLはこちらになります。

https://react-leaflet.js.org/docs/example-react-control

Typescriptに書き換えるにあたり、次の内容を追加しました。

interface PositionInterface { bottomleft:string, bottomright:string, topleft:string, topright:string } const POSITION_CLASSES:PositionInterface = { bottomleft: 'leaflet-bottom leaflet-left', bottomright: 'leaflet-bottom leaflet-right', topleft: 'leaflet-top leaflet-left', topright: 'leaflet-top leaflet-right', }

しかしながら、MinimapControlの部分で、エラーが出ました。

function MinimapControl({ position , zoom }:{position: string, zoom: number}) { ... const positionClass = (position && POSITION_CLASSES[position]) || POSITION_CLASSES.topright ...

このPOSITION_CLASSES[position]の部分で、エラーメッセージは以下になります。

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'PositionInterface'. No index signature with a parameter of type 'string' was found on type 'PositionInterface'.

自分で書いているソースコードをのせると以下のようになります。

import * as React from 'react' import {useState, } from 'react' import ReactDOM from 'react-dom' import { LatLngExpression } from 'leaflet'; import {MapContainer, TileLayer, Marker, Popup, useMapEvents, useMap, useMapEvent, Rectangle} from 'react-leaflet' import './mapPage.css'; import { createStyles } from '@material-ui/styles'; import { Theme } from '@material-ui/core/styles/createMuiTheme'; import makeStyles from '@material-ui/core/styles/makeStyles'; import { Fab } from '@material-ui/core'; interface PositionInterface { bottomleft:string, bottomright:string, topleft:string, topright:string } const POSITION_CLASSES:PositionInterface = { bottomleft: 'leaflet-bottom leaflet-left', bottomright: 'leaflet-bottom leaflet-right', topleft: 'leaflet-top leaflet-left', topright: 'leaflet-top leaflet-right', } const BOUNDS_STYLE = { weight: 1 } const useStyles = makeStyles((theme: Theme)=> createStyles({ root: { '& > *': { margin: theme.spacing(1), } }, extendedIcon: { marginRight: theme.spacing(1), } })) const LocationMarker: React.FC<{initial?:LatLngExpression}> = ({initial=null})=> { const [position , setPosition] = useState(initial) const map = useMapEvents({ click() { map.locate() }, locationfound(e) { setPosition(e.latlng) map.flyTo(e.latlng, map.getZoom()) }, }) return position === null ? null : ( <Marker position={position}> <Popup>You are here</Popup> </Marker> ) } function MinimapBounds({ parentMap, zoom }:{parentMap: any, zoom:number}) { const minimap = useMap() // Clicking a point on the minimap sets the parent's map center const onClick = React.useCallback( (e) => { parentMap.setView(e.latlng, parentMap.getZoom()) }, [parentMap], ) useMapEvent('click', onClick) // Keep track of bounds in state to trigger renders const [bounds, setBounds] = useState(parentMap.getBounds()) const onChange = React.useCallback(() => { setBounds(parentMap.getBounds()) // Update the minimap's view to match the parent map's center and zoom minimap.setView(parentMap.getCenter(), zoom) }, [minimap, parentMap, zoom]) // Listen to events on the parent map const handlers = React.useMemo(() => ({ move: onChange, zoom: onChange }), []) useEventHandlers({ instance: parentMap }, handlers) return <Rectangle bounds={bounds} pathOptions={BOUNDS_STYLE} /> } function MinimapControl({ position , zoom }:{position: string, zoom: number}) { const parentMap = useMap() const mapZoom = zoom || 0 // Memoize the minimap so it's not affected by position changes const minimap = React.useMemo( () => ( <MapContainer style={{ height: 80, width: 80 }} center={parentMap.getCenter()} zoom={mapZoom} dragging={false} doubleClickZoom={false} scrollWheelZoom={false} attributionControl={false} zoomControl={false}> <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> <MinimapBounds parentMap={parentMap} zoom={mapZoom} /> </MapContainer> ), [], ) const positionClass = (position && POSITION_CLASSES[position]) || POSITION_CLASSES.topright return ( <div className={positionClass}> <div className="leaflet-control leaflet-bar">{minimap}</div> </div> ) } function useEventHandlers(arg0: { instance: any; }, handlers: { move: () => void; zoom: () => void; }) { throw new Error('Function not implemented.'); } function MapPage() { const classes=useStyles(); return( <MapContainer center={[51.505, -0.09]} zoom={13} scrollWheelZoom={false} style = {{ height: '100vh' }} > <TileLayer attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> <LocationMarker /> </MapContainer> ) } export default MapPage

長文失礼しました。よろしくお願いいたします。


追記

エラーを解消したminiMapControlをついかしたところ、マップが表示されなくなってしまいました。miniMapControlもしくは、miniMapBoundsのどちらかに問題があると思うのですが...。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

かいけつしました。
InterfaceのIndexのTypeをきめなくてはいけなかったようです。

エラーがきえたのでひとまずさきにすすみますが、またふぐあいがでたら
ついかでかくかもしれません。

(パソコンのキーボードがとつぜんへんかんしなくなったのでひらがなでしつれいします。)

interface PositionInterface { [position: string]: string, bottomleft:string, bottomright:string, topleft:string, topright:string }

投稿2021/05/05 22:26

IsoNi

総合スコア32

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

K_3578

2021/05/06 03:54

解決されたのならこの回答を自己解決としてクローズしてください。 変換しなくなったのは誤操作で無変換にしたせいじゃないかな・・・
IsoNi

2021/05/06 04:51

ディクショナリーの扱いはわかったのですが、また躓いてしまって...。別スレ立てた方がいいですかね。 キーボードのほうは変換モードみたいな場所があるかと思ったのですが、とりあえずグーグルキーボードをつかうことにしました。 なにはともあれ返信ありがとうございます。一旦クローズします!
K_3578

2021/05/06 04:53

とりあえず今回の問題が片付いたのなら別スレ建ててもいいと思います。 今回の質問が関連するのならその旨を新規スレッドで記述してリンク貼っとけば良いかと。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問