Elixir/PhoenixでTypeScriptを使うことができるようにする。

下記の前提で書きました。

* docker-composeを使っていてappというコンテナ名
* assets配下にnpm installしている。

# install

```
docker-compose run app npm install typescript ts-loader source-map-loader @types/phoenix --prefix assets
```

```
akito-XPS-13-7390% docker-compose run app npm install typescript ts-loader source-map-loader @types/phoenix --prefix assets
Creating zyuso_app_run ... done
npm WARN source-map-loader@2.0.0 requires a peer of webpack@^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.1 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.1: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/watchpack-chokidar2/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ source-map-loader@2.0.0
+ ts-loader@8.0.14
+ @types/phoenix@1.5.1
+ typescript@4.1.3
added 22 packages from 67 contributors and audited 915 packages in 10.126s

47 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

# init

```
docker-compose run app ./assets/node_modules/.bin/tsc --init
```

```
akito-XPS-13-7390% docker-compose run app ./assets/node_modules/.bin/tsc --init
Creating zyuso_app_run ... done
message TS6071: Successfully created a tsconfig.json file.
```

# change a few things from the Typescript defaults.

```
{
  "compilerOptions": {
    "target": "es5",
    "module": "ESNext",
    "allowJs": true,
    "jsx": "react",
    "outDir": "./assets/dist/",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true
  },
  "exclude": [
    "/assets/node_modules/**/*"
  ]
}
```

# tell Webpack to recognise .ts files along with .js files
## change the first module rule to:

```assets/webpack.config.js
      rules: [
        {
          test: /\.(j|t)s$/,
          exclude: [
            '/assets/node_modules/'
          ],
          use: [
            {
              loader: 'babel-loader'
            },
            {
              loader: 'ts-loader'
            }
          ]
        },
```

## add an outermost "resolve" key after "module" as follows:

```assets/webpack.config.js
  resolve: {
    extensions: [".ts", ".js"]
  },
```

# app.js

```diff
-import "../css/app.scss"
+const _css = require("../css/app.scss");
```

[How to use CSS Modules with TypeScript and webpack](https://medium.com/@sapegin/css-modules-with-typescript-and-webpack-6b221ebe5f10)

# An example of loading ts check
## Welcome to Phoenix with Typescript!

`assets/js/hello.ts:`

```typescript
function greet(name: string): string {
  return "Welcome to " + name + " with Typescript!";
}
export default greet;
```

`assets/js/app.js` add the following lines toward the end:

```typescript
import greet from "./hello";
document.querySelector("section.phx-hero h1").innerHTML = greet("Phoenix");
```

## versions
Hex:    0.21.1
Elixir: 1.11.2
OTP:    23.2.1

## reference
https://levelup.gitconnected.com/elixir-phoenix-typescript-and-react-2020-edition-32ceb753705