LoginSignup
1
0

publicにあるJavaScriptの変数をTypeScriptで型定義して読む in React + Vite

Last updated at Posted at 2024-03-28

これはなに?なにがうれしい?

public配下にあるJavaScriptの設定ファイルをReactで読む必要があった。
この記事ではグローバルオブジェクトwindowを使用した方法をメインに紹介する。
この方法は、提供されたJSファイルなどを型定義して読み込みたい場合に使用できる。

試したけどダメだった方法

  • publicに定義した変数をsrc内の.d.tsでアンビエント宣言(declare)
    • publicに定義した変数と同名の変数をアンビエント宣言したからといって読み込めるわけではない
  • ES Modulesのimport/exportを使用
    • srcからsrcの外をimportできない
    • CommonJSのmodule.exports/requireはそもそもダメ

参考記事

コード

/index.html

Viteの場合はルート直下にindex.htmlがある。
対象JSは/public/js/configs.jsとする。

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React + TS</title>
  </head>
  <body>
    <div id="root"></div>
+++ <script type="module" src="/public/js/configs.js"></script>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

Create React Appの場合はpublic直下にある。

/public/index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>React Create App</title>
  </head>
  <body>
    <div id="root"></div>
+++ <script type="module" src="%PUBLIC_URL%/js/configs.js"></script>
  </body>
</html>

/public/js/config.js

オブジェクトとして定義してみる。

/public/config.js
window.configs = {
    windowConfig1: { keyString: 'windowConfigString1' },
    windowConfig2: { keyString: 'windowConfigString2' },
};

/src/@types/index.d.ts

config.jsにあるオブジェクトの形に沿って型を定義する。
TypeScriptがWindowインターフェースにwindowオブジェクトの持つべきプロパティやメソッドの型を定義している。
Windowインターフェースにアンビエント宣言することで宣言マージされ、Windowインターフェースが拡張される。

/src/@types/index.d.ts
interface Config {
    keyString: string;
}

interface Configs {
    [id: string]: Config;
}

// ここが本題
declare global {
    interface Window {
        configs: Configs;
    }
}

/src/*.*.tsx

読み込めていない場合を想定したほうがよい。

/src/pages/public/Js.tsx
import { type FC, memo } from 'react';
import { EXPORT_CONFIGS } from '/public/js/configs.js';

const Component: FC = () => {
    const windowConfigs = window.configs;

    return (
        <>
            {windowConfigs &&
                Object.keys(windowConfigs).map(key => (
                    <div key={key}>{windowConfigs?.[key]?.keyString}</div>
                ))}
        </>
    );
};

export const Js = memo(Component);

出力の抜粋

<div id="root">
    <div>windowConfigString1</div>
    <div>windowConfigString2</div>
</div>
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0