リレーションシップとスキーマ

■@modelとは?

https://docs.amplify.aws/cli-legacy/graphql-transformer/model/

@model注釈が付けられたオブジェクトタイプは、生成されたAPIの最上位エンティティです。@model注釈が付けられたオブジェクトは、AmazonDynamoDBに保存され、@authを介して保護され、@searchableを介して他のオブジェクトに関連付けられ、@connectionAmazonOpenSearchにストリーミングされます。@versionedディレクティブを適用して 、バージョンフィールドと競合検出をモデルタイプに即座に追加することもできます。

1つの@modelディレクティブで、次のAWSリソースを設定します。

  • デフォルトでPAY_PER_REQUEST課金モードが有効になっているAmazonDynamoDBテーブル。
  • 上記のテーブルにアクセスするように設定されたAWSAppSyncデータソース。
  • AWSAppSyncがお客様に代わって上記のテーブルを呼び出すことを可能にするデータソースにアタッチされたAWSIAMロール。
  • 最大8つのリゾルバー(作成、更新、削除、取得、リスト、onCreate、onUpdate、onDelete)ですが、これは@modelディレクティブのqueries、、、mutationsおよびsubscriptions引数を介して構成できます。
  • ミューテーションを作成、更新、および削除するための入力オブジェクト。
  • リストクエリおよび接続フィールドのオブジェクトをフィルタリングできるようにする入力オブジェクトをフィルタリングします。
  • リストクエリの場合、返されるオブジェクトのデフォルト数は100です。limit引数を設定することで、この動作をオーバーライドできます。

■@auth とは?

https://docs.amplify.aws/cli-legacy/graphql-transformer/auth/

アプリケーションがGraphQLAPIと対話するには、承認が必要です。

APIキーは、パブリックAPI(またはパブリックにしたいスキーマの一部)またはプロトタイピングに最適です。デプロイする前に有効期限を指定する必要があります。

IAM承認では、署名バージョン4を使用して、ロールに関連付けられたポリシーを使用してリクエストを行います。

AmazonCognitoユーザープールまたはサードパーティのOpenIDConnectプロバイダーによって提供されるOIDCトークンも承認に使用できます。これを有効にするだけで、ユーザーがAPIアクションへのトップレベルのアクセスを許可されるように認証する必要がある単純なアクセス制御が提供されます。

これらのトークンの一部として提供された、またはデータベースアイテム自体に設定された認証メタデータを活用するスキーマ上で@authを使用して、よりきめ細かいアクセス制御を設定できます。

@auth注釈が付けられたオブジェクトタイプは、APIの最上位の承認よりも追加の制御を提供する一連の承認ルールによって保護されます。プロジェクトのスキーマのオブジェクトタイプ定義とフィールド定義に、@authディレクティブを使用できます。

@modelアノテーションも付けられたオブジェクトタイプ定義で@authディレクティブ を使用すると、そのタイプのオブジェクトを返すすべてのリゾルバーが保護されます。フィールド定義でディレクティブを使用する @authと、親タイプで見つかった属性に基づいてアクセスを許可するリゾルバーがフィールドに追加されます。

■rules(@auth(rules:〜)

@authディレクティブを使用して、パブリック、サインインユーザー、ユーザーごと、およびユーザーグループごとのデータアクセスの承認ルールを構成します。承認ルールは、デフォルトで拒否の原則に基づいて機能します。

つまり、許可ルールが特に構成されていない場合、それは拒否されます。

上記のAWSでのルールの前提で、以下のコードを改めて見てみる。

AWS基礎学習

■(必須)初期設定をする

ログイン(アカウントの作成は済み)

料金アラートの設定

IAM(Identity and Access Management (IAM))で作業用ユーザーを作成

CloudTrailで操作ログを記録

■(ドメインを取得後、必要)Route53 ドメインを登録

ドメインの購入

Route53でDNSを設定

/*------------------------------------------------------

Webサーバーを使ったやり方

  • -----------------------------------------------------*/

VPCネットワークを構築

IPアドレスを決める

VPCを作成

サブネットを作成

ルーティングを設定

■EC2 Webサーバーを構築

EC2インスタンスを設置

SSHでEC2インスタンスに接続

Apacheをインストール

ファイアーウォールを設定

Elastic IPアドレスIPアドレスを固定

■RDS DBサーバーを構築

プライベートサブネットを作成

RDSを設置

WebサーバーからRDSに接続

そのほか、ECS、ECR、Fargate、Javascript SDK、をはじめ、

様々なバックエンドの設定が必要

/*------------------------------------------------------

サーバーレスのやり方

  • -----------------------------------------------------*/

■Amplify

(別ページ参照)

/*------------------------------------------------------

主にWebサーバーを使ったやり方での

参考URL(Amazon

  • -----------------------------------------------------*/

AWS SDK for JavaScript

https://aws.amazon.com/jp/sdk-for-javascript/

AWS での JavaScript

https://aws.amazon.com/jp/developer/language/javascript/?nc1=f_dr

■AWSFargate の Amazon ECS

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/AWS_Fargate.html

Amazon Elastic Container Registry とは

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/what-is-ecr.html?pg=ln&sec=hs

■Code Pipeline プロジェクトを作成

https://ap-northeast-1.console.aws.amazon.com/codesuite/codepipeline/start?region=ap-northeast-1

/*------------------------------------------------------

主にWebサーバーを使ったやり方での

参考URL(別サイト)

  • -----------------------------------------------------*/

Aws Code PipelineでReactjs/Nextのデプロイを自動化!ECSへ展開してみました

https://www.ragate.co.jp/blog/articles/2200

AWS Lambdaとは?】初心者にもわかりやすく解説

https://www.wafcharm.com/blog/aws-lambda-for-beginners/

https://ap-northeast-1.console.aws.amazon.com/ecs/home?region=ap-northeast-1#/getStarted

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/Welcome.html

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/docker-basics.html

https://zenn.dev/mame_06/articles/5ed6039a3a300b

https://www.ragate.co.jp/blog/articles/2200

https://cloudbees.techmatrix.jp/jenkins/

https://business.ntt-east.co.jp/content/cloudsolution/column-try-37.html

https://qiita.com/sugurutakahashi12345/items/dc23dab2613b0e6103e8

Electron 基礎

これが一番確かだった。

https://github.com/saltyshiomix/nextron

react-draft-wysiwyg

https://github.com/jpuri/react-draft-wysiwyg

https://www.npmjs.com/package/react-draft-wysiwyg

https://www.electronjs.org/docs/latest/tutorial/tutorial-packaging

https://www.electronjs.org/docs/latest/api/window-open

https://qiita.com/torisankanasan/items/983f4dae01090296e6d3

https://zenn.dev/erukiti/articles/933fc127f751aef45b4f

https://draftjs.org/docs/quickstart-api-basics

https://qiita.com/NozomuTsuruta/items/bb023a6f5bf6be3b3217

https://www.electronjs.org/ja/docs/latest/api/browser-window

https://blog.capilano-fw.com/?p=2593

https://ics.media/entry/8401/

https://www.electronjs.org/docs/latest/tutorial/tutorial-adding-features

https://zenn.dev/toono_f/articles/bd50ddd0a7bc76

https://morioh.com/p/29cf922e1f56

Electron Fiddle

https://www.electronjs.org/fiddle

Electron 公式

https://www.electronjs.org/ja/docs/latest/

Reactのスタイリングあれこれ

https://zenn.dev/chiji/articles/b0669fc3094ce3

Electron x Next.js でTodoアプリを作る

https://zenn.dev/tsuemura/scraps/f0bf7f8e7cb51a

Next.js + Electron がとても簡単になっていた

https://zenn.dev/erukiti/articles/933fc127f751aef45b4f

Electron with Typescript application example

https://github.com/vercel/next.js/tree/canary/examples/with-electron-typescript

Next.jsのexamples

https://nextjs.org/examples

Electron入門 ~ Webの技術でつくるデスクトップアプリ

https://zenn.dev/sprout2000/books/6f6a0bf2fd301c

Electron API レシピブック 2021

https://zenn.dev/sprout2000/books/3691a679478de2

Webpack環境下でBootstrapを使いながら、SassやJavascriptを使って簡単なフォーム作成

環境構築

  • npm init で初期化

    ディレクトリを作り、npm initで初期化

    →package.jsonをひたすらenterでつくる

  • 必要なnpmをインストール(今回はpug、sassを使う前提)

    →一気にインストール(npm i -D パッケージ名)

npm i -D webpack@5.37.1 webpack-cli@4.7.0 webpack-dev-server@3.11.2 @babel/core@7.14.3 @babel/preset-env@7.14.2 autoprefixer@10.2.5 babel-loader@8.2.2 clean-webpack-plugin@4.0.0-alpha.0 css-loader@5.2.4 file-loader@5.0.2 html-loader@2.1.2 html-webpack-plugin@5.3.1 image-webpack-loader@7.0.1 mini-css-extract-plugin@1.3.4 postcss@8.2.15 postcss-loader@5.3.0 pug-html-loader@1.1.5 resolve-url-loader@^4.0.0 sass@1.32.13 sass-loader@11.1.1 style-loader@2.0.0 url-loader@3.0.0
  • さらに、bootstrap関連のnpmもインストール(bootstrapは4.5.3を使う前提)
npm i -D bootstrap@4.5.3 jquery@3.5.1 popper.js@1.16.0 @popperjs/core@2.9.2
  • package.jsonを整える

    →デバックが毎回面倒なので、短縮コマンドをpackage.jsonに入れておく。

  "scripts": {
    "start": "npx webpack serve --mode=development",
    "build": "webpack --mode=development",
    "build:dev": "webpack"
  },
  • package.jsonの修正形はこちら(mainファイルをリネームしているのに注意)
{
  "name": "test2",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "start": "npx webpack serve --mode=development",
    "build": "webpack --mode=development",
    "build:dev": "webpack"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.14.3",
    "@babel/preset-env": "^7.14.2",
    "animejs": "^3.2.1",
    "autoprefixer": "^10.2.5",
    "babel-loader": "^8.2.2",
    "clean-webpack-plugin": "^4.0.0-alpha.0",
    "css-loader": "^5.2.4",
    "ejs-html-loader": "^4.0.1",
    "file-loader": "^5.0.2",
    "gsap": "^3.6.1",
    "html-loader": "^2.1.2",
    "html-webpack-plugin": "^5.3.1",
    "image-webpack-loader": "^7.0.1",
    "mini-css-extract-plugin": "^1.3.4",
    "postcss": "^8.2.15",
    "postcss-loader": "^5.3.0",
    "pug-html-loader": "^1.1.5",
    "resolve-url-loader": "^4.0.0",
    "sass": "^1.32.13",
    "sass-loader": "^11.1.1",
    "style-loader": "^2.0.0",
    "url-loader": "^3.0.0",
    "vue": "^2.6.12",
    "vue-cli": "^2.9.6",
    "vue-loader": "^15.9.7",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^5.37.1",
    "webpack-cli": "^4.7.0",
    "webpack-dev-server": "^3.11.2"
  },
  "dependencies": {
    "bootstrap": "^4.5.3",
    "jquery": "^3.5.1",
    "popper.js": "^1.16.0",
    "@popperjs/core": "^2.9.2",
  }
}
  • 作業ディレクトリをつくる(dist→コンパイル後、src→コンパイル前の作業用)
  • srcフォルダ内のディレクトリをつくる

    css(オリジナルのsassを入れていく)

    →images(画像など)

    →js(オリジナルのjavascript関連)

    →templates(htmlやpugを入れる)

  • webpack.config.jsをつくる(設定ファイル)

    →ルートディレクトリにwebpack.config.jsという名前で空のjsファイルをつくる

    →コアになるwebpack.config.jsの最初の状態は以下。

const path = require('path');
module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
  },
};
  • さらに、npmでインストールしていったパッケージを入れていって、整理していったものがこちら
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  mode: 'development',
  entry: {
    main: './src/js/main.js'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'js/main.js',
  },
  module: {
    rules: [
      {
        test: /\.js/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env', { "targets": "> 0.25%, not dead" }],
              ],
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        use: [
          {
            // loader: 'style-loader',
            loader: MiniCssExtractPlugin.loader, // 追加
          },
          {
            loader: 'css-loader',
            options: {
              url: false,
              sourceMap: true,
              importLoaders: 2,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              sourceMap: true,
              postcssOptions: {
                plugins: ["autoprefixer"],
              },
            },
          },
          {
            loader: "sass-loader",
            // options: {
            //   sourceMap: true,
            // },
          },
        ],
      },
      {
        test: /\.(gif|png|jpg|svg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]',
        },
        use: [
          // {
          //   loader: 'file-loader',
          //   options: {
          //     esModule: false,
          //     name: 'images/[name].[ext]',
          //   },
          // },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65,
              },
            },
          },
        ],
      },
      {
        test: /\.pug/,
        use: [
          {
            loader: 'html-loader',
          },
          {
            loader: 'pug-html-loader',
            options: {
              pretty: true,
            }
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/templates/index.pug',
      filename: "index.html",
    }),
    new CleanWebpackPlugin(),
  ],
  devtool: "source-map",
  target: ["web", "es5"],
  stats: {
    children: true,
  },
};
  • src/jsへmain.jsをつくる

    →とりあえず空で

    JavascriptjQuery デバックでじりじり修正 console.log

    →モジュール化の考え。exportの外部ファイルをimport

import costom from './costom.js';
export default () => {
}
  • 新規でindex.pugをつくる
doctype html
html
  body
    h1 My Site
    p Welcome to my super lame site.
  • Sassを使う準備

    →src/cssディレクトリにstyle.scssファイルをつくる。

    →webpack.config.jsでsassファイルがコンパイルできるように記載する

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  mode: 'development',
  entry: {
    main: './src/js/main.js'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'js/main.js',
  },
  module: {
    rules: [
      {
        test: /\.js/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env', { "targets": "> 0.25%, not dead" }],
              ],
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        use: [
          {
            // loader: 'style-loader',
            loader: MiniCssExtractPlugin.loader, // 追加
          },
          {
            loader: 'css-loader',
            options: {
              url: false,
              sourceMap: true,
              importLoaders: 2,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              sourceMap: true,
              postcssOptions: {
                plugins: ["autoprefixer"],
              },
            },
          },
          {
            loader: "sass-loader",
            // options: {
            //   sourceMap: true,
            // },
          },
        ],
      },
      {
        test: /\.(gif|png|jpg|svg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]',
        },
        use: [
          // {
          //   loader: 'file-loader',
          //   options: {
          //     esModule: false,
          //     name: 'images/[name].[ext]',
          //   },
          // },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65,
              },
            },
          },
        ],
      },
      {
        test: /\.pug/,
        use: [
          {
            loader: 'html-loader',
          },
          {
            loader: 'pug-html-loader',
            options: {
              pretty: true,
            }
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: './css/style.css',
    }),
    new HtmlWebpackPlugin({
      template: './src/templates/index.pug',
      filename: "index.html",
    }),
    new CleanWebpackPlugin(),
  ],
  devtool: "source-map",
  target: ["web", "es5"],
  stats: {
    children: true,
  },
};
  • src/main.jsへsassが読み込まれるようにする
import '../css/style.scss'
  • sassの動作チェック

    →Sassのネスト構造

    →Sassの変数

    →Sassのループ

  • bootstrapが使えるようにする(sass側)

    →sass.scssにインポート

@import "~bootstrap/scss/bootstrap.scss";
  • bootstrapが使えるようにする(webpack.config.js)
const webpack = require('webpack');
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery'
    }),
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  mode: 'development',
  entry: {
    main: './src/js/main.js'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'js/main.js',
  },
  module: {
    rules: [
      {
        test: /\.js/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env', { "targets": "> 0.25%, not dead" }],
              ],
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        use: [
          {
            // loader: 'style-loader',
            loader: MiniCssExtractPlugin.loader, // 追加
          },
          {
            loader: 'css-loader',
            options: {
              url: false,
              sourceMap: true,
              importLoaders: 2,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              sourceMap: true,
              postcssOptions: {
                plugins: ["autoprefixer"],
              },
            },
          },
          {
            loader: "sass-loader",
            // options: {
            //   sourceMap: true,
            // },
          },
        ],
      },
      {
        test: /\.(gif|png|jpg|svg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]',
        },
        use: [
          // {
          //   loader: 'file-loader',
          //   options: {
          //     esModule: false,
          //     name: 'images/[name].[ext]',
          //   },
          // },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65,
              },
            },
          },
        ],
      },
      {
        test: /\.pug/,
        use: [
          {
            loader: 'html-loader',
          },
          {
            loader: 'pug-html-loader',
            options: {
              pretty: true,
            }
          },
        ],
      },
    ],
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery'
    }),
    new MiniCssExtractPlugin({
      filename: './css/style.css',
    }),
    new HtmlWebpackPlugin({
      template: './src/templates/index.pug',
      filename: "index.html",
    }),
    new CleanWebpackPlugin(),
  ],
  devtool: "source-map",
  target: ["web", "es5"],
  stats: {
    children: true,
  },
};
  • bootstrapが使えるようにする(main.js)
import "popper.js"
import "bootstrap"

Bootstrapでフォームを組み立てる

どうしてWebpackが必要か?(座学)

■stateをオブジェクトとしてまとめて取り扱うプロセス

import { useState } from "react";

export default function App() {
  const [state, setState] = useState({
    pip: false,
    playing: true
  });

  return (
    <div className="App">
      <p>あああ</p>
    </div>
  );
}

このようにstateをオブジェクト形式で表した場合、例えば、

 console.log(state);

とすると、

{pip: false, playing: true}

となって返ってくる。

なので、個別に取得したかったら

 console.log(pip.state);

などとする必要がある。

そこで、

  const {
    pip,
    playing
  } = state;

とすると、

 console.log(pip);

でpipキーのvalueが取れるようになる。

■スプレッド構文(spread syntax)について改めて理解

const arr = [1, 2, 3]

という数値だけが入ったシンプルな配列を見てみる。

これをスプレッド構文(...)で「展開」してみると

console.log(...arr)
//1 2 3

とコンソールで表示される。

このことを「配列構造とオブジェクト構造を展開する」と言うらしい。

これを試しに

const arr1 = ...arr

とすると、

SyntaxError: /src/App.js: Unexpected token, expected "," (22:2)

となる。

このことは、スプレッド構文(...)を定義している以下の仕様に基づくことになる。

「The spread (...) syntax allows an iterable, such as an array or string, to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected.

(スプレッド (...) 構文を使用すると、配列や文字列などのイテラブルを、0 個以上の引数 (関数呼び出しの場合) または要素 (配列リテラルの場合) が期待される場所に展開できます。)」

つまり、スプレッド構文が使える場所は、引数か、配列、そしてオブジェクトなのだ。

■stateのオブジェクト化とスプレッド構文が組み合わさって動く時の仕様

ここで、stateの動きを確認すべく、buttonのonClickで状態関数に変化を与える。

import { useState } from "react";
export default function App() {
  const [state, setState] = useState({
    pip: false,
    playing: true
  });
  const { pip, playing } = state;
  const handle = (e) => {
    setState({ pip: true });
  };
  // console.log(state);
  const arr = [1, 2, 3]
  // const arr1 = ...arr
  console.log(state)
  return (
    <div className="App">
      <p>あああ</p>
      <button onClick={handle}>ボタン</button>
    </div>
  );
}

ボタンを押す前のconsole.logは

{pip: false, playing: true}

と定義してあるオブジェクトが予想通り出力されるが、ボタンをクリックすると

{pip: true}

と、playingのプロパティが消えてしまう。

これは、

  const handle = (e) => {
    setState({ pip: true });
  };

  const handle = (e) => {
    setState({...state, pip: true });
  };

としてやる必要があるのだ。

このことは、オブジェクトリテラルでのスプレッド構文という仕様が、強く関わっている。

スプレッド構文_mdn

スプレッド演算子、レストパラメーター、分割代入

■スプレッド演算子

スプレッド演算子(...)は、配列の全ての値を一括で「展開」できる、という機能である。

push()について復習。配列やオブジェクトは「参照型」。値そのものではなく、値への参照を持っている。参照先のアドレスが変わらなければ、メモリの中身である配列やオブジェクトの中身を変更することができる。

よって、以下の例で、push()を使って、activeHobbiesに配列を追加するとしたら、

const hobbies = ["Spotrs", "Viking", "Razicon"];
const activeHobbies = ["Hiking"];

activeHobbies.push(hobbies[0], hobbies[1], hobbies[1]);

console.log(activeHobbies);
>>>['Hiking', 'Spotrs', 'Viking', 'Viking']

となる。

これを、スプレッド演算子(...)を利用すると、

const hobbies = ["Spotrs", "Viking", "Razicon"];
const activeHobbies = ["Hiking", ...hobbies];

console.log(activeHobbies);
>>>['Hiking', 'Spotrs', 'Viking', 'Viking']

と記述量が大きく減る。

スプレッド演算子(...)は、配列だけでなく、オブジェクトにも使える。

const person ={
    name: "shingo",
    age: 46
}
const person2 = {
    ...person
}

console.log(person);
console.log(person2);
>>>{name: 'shingo', age: 46}
>>>{name: 'shingo', age: 46}

こうすることで、簡単にオブジェクトも中身をそのまま複製できる。

■レストパラメーター(残余引数=残りのパラメーター)

今までは、あらかじめ「決まった数の引数」を受け取る関数を書いてきたが、「任意の引数」を受け取れるようにするにはどうしたら良いか?

そこで活躍するのが、レストパラメーターである。

例えば

const add = () => {

}

const addedNumbers = add(1, 7, 89, 4, 73);
console.log(addedNumbers);

このような任意のパラメーターを受け取る関数を考える時、どのようにすれば良いか?

そこで活躍するのがスプレッド演算子(...)。スプレッド演算子は、パラメーターを渡すときだけでなく、受け取る時にも使うことができる。

const add = (...numbers) => {
}

このようにして、受け取りたい値を配列にして渡すことができる。配列名は任意で大丈夫。

この関数に渡されたパラメーターが、全て一つの配列にマージされて、一つの関数に渡される。

つまり、「1, 7, 89, 4, 73」が[1, 7, 89, 4, 73]として渡されて、... で展開される、という流れになる。

さらに、typescriptの場合は

const add = (...numbers: number[]) => {

}

とnumberの配列と型を指定する。

これで、numbersを数字の配列として扱うことができる、という流れである。

関数の中身を考える。合計値を計算することを考える。

一つはforを使い、中身をループさせて合計するやり方。

もう一つはreduce()を使って、配列の中身を何らかの一つの値にするやり方。

const add = (...numbers: number[]) => {
    numbers.reduce(() = {}, 0)
}

reduceの一つ目の関数は、計算を行う関数、二つ目は初期値。

これを、accumulator(蓄積した結果)とcurrentValue(現在の値)という引数を使って、計算結果を返す。

const add = (...numbers: number[]) => {
    return numbers.reduce((accumulator, currentValue) => {
        return accumulator + currentValue;
    }, 0)
}
const addedNumbers = add(1, 7, 89, 4, 73);
console.log(addedNumbers);

これが「レストパラメーター」である。

今回は「任意の引数」を受け取る例だったが、決まった数の引数であれば、タプル型と組み合わせて使うと効果的。

例えばこのように。

const add = (...numbers: [number, number, number]) => {
    〜略〜
}

■分割代入(デストラクチャリング)

ここでも、スプレッド演算子(...)が活躍。

配列の分割代入は以下になる。

const hobbies = ["Spotrs", "Viking", "Razicon", "Cooking", "Racing"];
const [hobby1, hobby2, ...restHobbies] = hobbies;

console.log(hobby1)
console.log(hobby2)
console.log(...restHobbies)
>>>Spotrs
>>>Viking
>>>Razicon Cooking Racing

と、分割できる。

次はオブジェクト。

const person = {
    firstName: "shingo",
    age: 46
}
const {firstName, age} = person;

console.log(firstName);
console.log(typeof(firstName));
>>>shingo
>>>string

と出力できる。

このことは、オブジェクトを変数(この場合はconst<定数>)に分割して格納することができる、ということを示している。

また、名前を変更できる。

const {firstName:changeName, age} = person;

このようにすることで、firstNameというconst(定数)名から、changeNameという定数名に変更できる。