ゆずめも

メモ的なブログです。主に勉強した事について書いてます。

今からReactを始める人に向けた型の話

周りでこれからReact始める人とかが増えてきて、以外と知られてないんだな〜ってことがあったのでReactに型をつけるというかTypeScript(以下ts), Flowと prop-typesの関係について書く

tl;dr

  • prop-typeはやめとけ
  • tsはいいぞ

prop-typesとは

昔はReactのcoreに入ってけどFlowが出てきたりでcoreから切り離して後方互換性のためにいパッケージとして切り出されたもの

Prop-TypesでもコンポーネントがどのようなPropsを受け取るのかを表現できなくはないが、Flow, tsに比べると表現力が乏しいので、これから作るもので使うのはおすすめしない

表現力が乏しいっていうのはPropTypesだとx{a: number, b: number}のオブジェクト、yはただのnumberだとした時に以下のような定義になる

MyComponent.propTypes = {
  x: PropTypes.Object.isRequired,
  y: PropTypes.Number.isRequired
}

これがFlowやtsだと以下のように書けるのでxabというプロパティを持っていることがわかる(例はtypescript)

type Props = {
  x: {a: number, b: number}
  y: number
}
function MyComponent(props: Props) {}

Flow

Flowはfacebook製のOSSOCamlで実装されている

https://flow.org/

最近のは使ってないのでよくわかってないが、前に使った経験的にはtsより推論が賢かったイメージがある

Reactをよくある構成で使う時はflow-typedで型が見つかるが、ちょっと珍しいライブラリとかだと型定義自作する所から始まるイメージ 記事書きながら見てみたらめっちゃ増えてたけどtsに比べるとちょっと辛そう

github.com

TypeScript

令和の時代はライブラリもtsで書きますよねって発表されてるくらい来てるts

使い捨ての処理書く時とか以外は3, 4年前から仕事でもずっとts書いてる

Flowでいうflow-typed的な有志による型定義が集まってるDefinitelyTypedがとにかく色々あるので、最近はライブラリがtypescript用の型定義を用意してくれてるものも増えたけど、無い時はDefinitelyTyped探せばよっぽど変なライブラリを持ってこない限りは大体ここにあるイメージがある

型があると補完だったり、静的チェックだったりとにかく良いし、型推論が優秀なので関数のインターフェースをちゃんと書けば特に型を書かなくてもいい感じに推論してくれるので基本的にメリットを感じることはあってもデメリットを感じることはないです

まとめ

そもそもFlow, tsとprop-typesを同じレベルで言っていいのか?とか思ったけど今後説明しなくて良いように書いた

個人的にはtsをサポートしてるライブラリ等も増えてきてるし、関西だとkansai.tsとかあったりするので特段理由が無ければts使ってればいいのでは無いかと思う kansaits.connpass.com

最後に型がいい感じに書けた時とっても気持ちいいのでtsはいいぞ〜

Go Modules時代のimport

最近ちょこちょこGolangを勉強していて、1.13になってデフォルトONになるgo modulesを使った時にimportをどうやるのかわからなくて困ったのでメモ

tl;dr

go.modmodule項目とwikiを見て

github.com

gopath mode

go modulesじゃない時はGOPATHがあったのでimportの時は$GOPATH/srcが見えないけどついてるイメージでプロジェクトがgithub.com/yuzu441/nogiなのであれば

import "github.com/yuzu441/nogi/package"

と書けば指定したパッケージがimportできる

module-aware mode

go modulesを使う設定にするとGOPATHがないのでパッケージ名の指定をどうするのかがわからなかったが、githubwikiを見ていると答えが書いてあった

go modules環境ではgo.modというファイルがあって

これを生成するのにgo mod initというコマンドを使うんだけど、これの後ろにgithub.com/yuzu441/nogiのように指定してやる

go mod init github.com/yuzu441/nogi

するとgo.modファイルの先頭にmodule github.com/yuzu441/nogiのように記述されgopathモードの時と同じようにパッケージを参照できる

なので以下のように実行すると

go mod init yuzu441/nogi

yuzu441/nogiでアクセスできる

import "yuzu441/nogi/package"

のように参照することができる

サンプルコード

go mod init yuzu441/samplego.modを生成したという仮定でのサンプル

// service/calc.go
package service

func Add(x int, y int) int {
    return x + y
}

// main.go
package main

import (
    "strconv"

    "yuzu441/sample/service"
)

func main() {
    result := service.Add(1, 2)
    println("add result: " + strconv.Itoa(result))
}

echoのバナー表示を消す

golangのwebフレームワークのechoで実行時に表示されるバナー(ロゴみたいなEcho文字列)がGoogleAppEngineのログ表示を見づらくしてしまっていたので、それの表示を止める

要するに↓のこれを表示しないようにします

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.1.5
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8080

やり方

HideBannerというオプションがあるのでそれにtrueを設定すると表示されなくなる

package main

import (
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
    "net/http"
    "os"
)

func main() {
    e := echo.New()

    // このオプションを設定する
    e.HideBanner = true

    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    e.GET("/", hello)

    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }
    e.Logger.Fatal(e.Start(":" + port))
}

func hello(c echo.Context) error {
    return c.String(http.StatusOK, "Hello World")
}