お知らせ

現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。

MSYS2

初回セットアップ

pacman -Syuu
# 一回落ちるのでもう一度起動して
pacman -Syuu

入れとくと便利なものたち

pacman

pacman -sS unzip
pacman -S --noconfirm unzip
pacman -sS diffutils
pacman -S --noconfirm diffutils
pacman -sS dnsutils
pacman -S --noconfirm dnsutils
pacman -sS openssh
pacman -S --noconfirm openssh
pacman -sS patch
pacman -S --noconfirm patch
pacman -sS perl
pacman -S --noconfirm perl
pacman -sS zsh
pacman -S --noconfirm zsh
pacman -sS git
pacman -S --noconfirm git
# prompt用に退避させる
mv /usr/bin/git /usr/bin/msys2_git

バイナリ追加

  • jq
    • chocoから入れる
  • dig
    • .x64.zipが入っているバージョンを/usr/binに突っ込む

dotfileの設定

https://github.com/Lycolia/my-dotfiles

Windows Terminal連携

{
  "defaultProfile": "{17da3cac-b318-431e-8a3e-7fcdefe6d114}",
  "profiles": {
    "defaults": {},
    "list": [
      {
        "commandline": "C:/env/msys64/msys2_shell.cmd -defterm -here -use-full-path -no-start -msys -shell zsh",
        "font": {
          "face": "Consolas",
          "size": 11
        },
        "guid": "{17da3cac-b318-431e-8a3e-7fcdefe6d114}",
        "icon": "C:/env/msys64/mingw64.ico",
        "name": "MINGW64 / MSYS2",
        "colorScheme": "VSCode"
      }
    ]
  },
  "schemes": [
    {
      "name": "VSCode",
      "background": "#1e1e1e",
      "foreground": "#d4d4d4",
      "black": "#000000",
      "blue": "#2472c8",
      "brightBlack": "#666666",
      "brightBlue": "#3b8eea",
      "brightCyan": "#29b8db",
      "brightGreen": "#23d18b",
      "brightPurple": "#d670d6",
      "brightRed": "#f14c4c",
      "brightWhite": "#e5e5e5",
      "brightYellow": "#f5f543",
      "cyan": "#11a8cd",
      "green": "#0dbc79",
      "purple": "#bc3fbc",
      "red": "#cd3131",
      "white": "#e5e5e5",
      "yellow": "#e5e510"
    }
  ]
}

msys2_shell.cmdのCLI Optionsの意味合い

-mingw32 | -mingw64 | -ucrt64 | -clang64 | -msys[2]

それぞれで実行環境が変わる
-msysで基本的に良い

-defterm | -mintty | -conemu

開くターミナルの指定

  • -defterm
    • 標準ターミナルで開く
    • Windows TerminalやVSCodeで開く場合はこれを指定する
  • -mintty
    • Minttyが起動する
  • -conemu
    • Conemuが起動する

-here

現在の作業フォルダをカレントディレクトリとして開く

-where DIRECTORY

指定ディレクトリをカレントディレクトリとして開く

-[use-]full-path

Windowsのパスを継承する

-no-start

新窓で開かない
指定しない場合startコマンドでシェルが起動する

-shell SHELL

ログインシェルを指定する
例えば-shell zshならzshがログインシェルになる
未指定の場合bashがログインシェルになる
msys2_shell.cmdを書き換えて実現することもできるが、アップデートで書き換えた内容が消えることがあるのでオススメしない

-help | --help | -? | /?

ヘルプの表示

投稿日:
言語::TypeScriptジャンル::調査

TypeScriptをぼちぼちやってきた中で、型推論が素直に決まらないみたいな所が出てきたので書き置きとして残しておきます
具体的には何かしらの関数を通して処理を隠蔽すると上手くいかなくなるケースがあります

型が推論されないケース

検査関数的なものを通した場合に、後続処理で期待通り型が推論されなくなるケースです

その1

type HogePiyo = 'hoge' | 'piyo';

type InputProps<ValueT> = {
  value: ValueT;
  error: string;
};

const required = (val: string) => {
  return val === '';
};

const registerHogePiyo = (value: HogePiyo) => {
  console.log('register', value);
};

const input: InputProps<HogePiyo | ''> = {
  value: '',
  error: '',
};

if (required(input.value)) {
  input.error = 'ERR';
  console.error(input.error);
} else {
  // ここでは input.value は 'hoge' | 'piyo' となるはずだが
  // TSC は 'hoge' | 'piyo' | '' と解釈する
  registerHogePiyo(input.value);
}

その 2

type HogePiyo = 'hoge' | 'piyo';

type InputProps<ValueT> = {
  value: ValueT;
  error: string;
  hasError: boolean;
};

const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
  if (obj.value === '') {
    return { value: '', error: '必須入力です', hasError: true };
  } else {
    return { value: obj.value, error: '', hasError: false };
  }
};

const registerHogePiyo = (value: HogePiyo) => {
  console.log('register', value);
};

const input: InputProps<HogePiyo | ''> = {
  value: '',
  error: '',
  hasError: false,
};

const result = required(input);
if (result.hasError) {
  console.error(result.error);
} else {
  // ここでは input.value は 'hoge' | 'piyo' となるはずだが
  // TSC は 'hoge' | 'piyo' | '' と解釈する
  registerHogePiyo(result.value);
}

export {};

型を推論されるようにしたケース

オブジェクトに型判定用のプロパティを生やしasで型を明示することでクリアしています

type HogePiyo = 'hoge' | 'piyo';

type InputProps<ValueT> = {
  value: ValueT;
  error: string;
  hasError: boolean;
};

const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
  if (obj.value === '') {
    return { value: '', error: '必須入力です', hasError: true } as {
      value: '';
      error: string;
      hasError: true;
    };
  } else {
    return { value: obj.value, error: '', hasError: false } as {
      value: ValueT;
      error: string;
      hasError: false;
    };
  }
};

const registerHogePiyo = (value: HogePiyo) => {
  console.log('register', value);
};

const input: InputProps<HogePiyo | ''> = {
  value: '',
  error: '',
  hasError: false,
};

const result = required(input);
if (result.hasError) {
  console.error(input.error);
} else {
  registerHogePiyo(result.value);
}

export {};

あとがき

  • Assertion Functionsを使う方法もあると思いますが、何も考えずAssertion Functionsを書くと次のような弊害があり、積極的に採用しづらいと考えています
    • 何もしていなければ基本的にバンドル後のソースコードに出てくる
      • 要するにバンドルサイズが大きくなります
    • throwを書く必要性があり、バンドル後に残っている以上、このthrowcatchする必要性がある
      • 無意味な実装工数が生まれる
    • そもそも論としてAssertion Functionsを書く工数が生まれる
    • Assertion Functionsの振る舞いを見ている限り、asに限りなく近く、ぶっちゃけasで書いたほうが楽
  • 絶対にasを使わず現実的な工数で開発するというのは、割と非現実ではないかという感触があります
    • 個人的に型推論はIDEが勝手にやってくれるおかげで楽ができるシステムだと考えているので、型推論の補佐をする仕組みに工数をかけるというのは本末転倒な気がしています
  • 品質は大切なことですが、反面で少なくないビジネスには期限もあります
    • 品質に寄せすぎた過剰に冗長なコードも、納期に寄せすぎた脆弱性不具合山盛りスパゲティコードもどちらも考えものであり、その辺のバランスが上手くとれるやり方がなんかないかなーと考えることはしばしばあります