$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

TypeScript 3.7.2でjsonをimportした際に、json構造によっては二度目の代入が型エラーになるバグを踏んだ

表題のとおり。TypeScript 3.8.0-dev.20191126では直っていたので、3.8.0が来るまで気長に待ちましょう。

再現コードはこちら。

https://github.com/shibayu36/typescript-json-module-bug/blob/master/test.ts

import data from "./data.json";
type Data = {
  a: string;
  array: {
    hoge: number;
  }[];
};

const d1: Data = data;
const d2: Data = data; // type check error ocurred

const copiedData = data;
const d3: Data = copiedData; // type check error didn't occur

const data2 = {
  a: "b",
  c: "d",
  array: [{ hoge: 1 }, { hoge: 2, foo: "bar" }]
};

const d4: Data = data2;
const d5: Data = data2; // type check error didn't occur

https://github.com/shibayu36/typescript-json-module-bug/blob/master/data.json

{
  "a": "b",
  "c": "d",
  "array": [{ "hoge": 1 }, { "hoge": 2, "foo": "bar" }]
}
  • jsonにobjectのarrayが含まれていて、かつobjectのarray中に余分なフィールドが含まれている時(上記の例ならfooフィールド)、importした構造を一度目に代入する時は成功するのに、二度目に代入する時は型エラーが発生する
    • d1とd2への代入
  • しかし、dataを一度別の変数に代入すると、同じ型の変数にも代入が成功する
    • d3への代入
  • importではなく普通にobjectを作成した時(data2)、それは何回代入しても型チェックは通る

Next.jsチュートリアルやった

SPAをやるにあたって、Server Side Renderingの仕組みも知っておいたほうが良いと感じ、Next.jsについて学んでみた。チュートリアルがよく出来ていたので、これをベースに学んだ。

チュートリアルをやった感じ、Next.jsは以下のようなものがメインの機能のフレームワークだなと思った。使い方はシンプルだけど、面倒なことは結構やってくれて便利。

  • ファイルベースのルーティングをしてくれて
  • Server Side Renderingをしてくれて
  • いい感じにjsをchunkで分けてくれる
    • しかもページに存在するLinkを見て、関係するsourceをprefetchしてくれたりする

これまでGraphQL/React/Next.jsと勉強してきたけど、ここまで手軽にSPA & Server Side Renderingが出来るなら、SEOとか関係するサイトでも全てSPAでいいなという気持ちになった。

チュートリアルメモ

特に重要なポイントとしては、

  • ファイルベースのルーティングの使い方
  • Linkの使い方
  • getInitialProps

あたりだろうか。



[id].js的なファイルの場合、なんかこういう書き方でLinkしたほうがよい。

<Link href=“/p/[id]” as={`/p/${props.id}`}>

以下のようにするとサーバに直接アクセスしたことになってしまい(クライアントサイドでルーティングが存在しないとみなされる)、リダイレクトしているのと同じ挙動となり、全体がSSRされるので遅い。

<Link href={`/p/${props.id}`}>


https://nextjs.org/learn/basics/fetching-data-for-pages/finally

getInitialPropsを定義することで、サーバサイドレンダリング時はサーバで、クライアントサイドレンダリング時はクライアントでそれぞれ実行される。

const Post = props => (
  <Layout>
    <h1>{props.show.name}</h1>
    <p>{props.show.summary.replace(/<[/]?[pb]>/g, '')}</p>
    <img src={props.show.image.medium} />
  </Layout>
);

Post.getInitialProps = async function(context) {
  const { id } = context.query;
  const res = await fetch(`https://api.tvmaze.com/shows/${id}`);
  const show = await res.json();

  console.log(`Fetched show: ${show.name}`);

  return { show };
};

export default Post;


https://nextjs.org/learn/basics/styling-components/styling-our-home-page

<style jsx>{`
   …
`}</style>

のような書き方をすることで、そのコンポーネント内でスタイルを適用できる。テンプレート文字列でCSSを渡すこと

https://nextjs.org/learn/basics/styling-components/no-effect-for-nested-components

ネストされたコンポーネントにはstyleは適用されないので、適用するstyleはそのコンポーネントで定義すること。https://github.com/zeit/styled-jsx#one-off-global-selectors global selectorというのもある。

https://nextjs.org/learn/basics/styling-components/global-styles

<style jsx global>を使うことで、globalにstyle適用することが出来る。外部からインストールしたコンポーネントにスタイルを当てたい時に便利(例えばreact-markdown)。

styled-jsxについて他いろいろは https://github.com/zeit/styled-jsx を見よう。


https://nextjs.org/learn/basics/deploying-a-nextjs-app/build-and-start next buildしてnext startすればサーバを立ち上げられる。本番ではこれを使う。

「エンタープライズアプリケーションアーキテクチャパターン」を読んだ

ソフトウェア設計に関する知識が昔のままで止まっていて、最近の設計のためのワードはぼんやりと理解できるものの、はっきりと分かっていないなと感じていた。そこでまだ読んでいなかった設計に関する本を読もうと思い、まずは「エンタープライズアプリケーションアーキテクチャパターン」を読んだ。

これまでプログラムを書いていた経験からか、全く知らないパターンというのは少なかったのだけど、これまでの経験知に名前付けを出来たのは良かった。特にシングルテーブル継承、具象テーブル継承、クラステーブル継承の話は面白く、どれも見たことあるしメリット・デメリット分かる!という気持ちになった。

次は エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践) を読もうかなと思う。

読書ノート

* 行データゲートウェイはO/Rマッパー感が強い 1630
    * 実際には行データゲートウェイ、テーブルデータゲートウェイ、アクティブレコード、データマッパーなどのどの思想でもORMを実装できるので、どういう思想のORMかを知っておくと良い選択をできそう
* テーブルデータゲートウェイはperlで書いているときに良く自分が使っている手法?データマッパーのほうかな? 1647
* レコードオブジェクト自体にDB操作も持つアクティブレコード、DB操作とドメインモデルを分離するデータマッパー 1695
* 構造的なマッピングに関するパターンについては、Apollo Clientのキャッシュの処理とイメージが似ている気がする。一意フィールドとか 1842
* シングルテーブル継承、具象テーブル継承、クラステーブル継承はたしかに全部見たことある 1937 ※
    * それぞれの特性はめっちゃ納得できること書いてある 1956
* アプリケーションコントローラーは、プレゼンテーション層内でさらに再利用したい時に使うって感じかな? 2222
* トランザクションスクリプトというのは、引数がプリミティブなものだけで、手続きを記述していくものなのかな 3721
* ドメインモデルは普通のオブジェクト指向って感じ 4000
* テーブルモジュールはよくあるテーブル操作と対応するクラスっぽい 4091
* サービスレイヤーはユースケース層といえるのか? 4451
* テーブルデータゲートウェイがテーブル操作と紐づくのか? 4452
* 行データゲートウェイは、行オブジェクトにinsertとかdeleteとかがあるやつ 4727
    * さらにロジックが追加されていくとアクティブレコードへ 4924
* データマッパーはいつもよく使ってる行データにdbアクセスがないやつな気がする 5062
* ユニットオブワークはデータの実際の更新処理を遅延させ、一括で行うものっぽい。つまりアプリケーションコード内でトランザクションを実装しているイメージ 5688
* 一意マッピングはapollo clientのキャッシュみたいなやつっぽい 5804