Immutable.js 4.0.0-rc.9はFlowでもTypeScriptでもgetとsetの文字列を検査してエラーを出します
Immutable.jsのRecordについて情報を察知しました.
class extendでRecordを継承して独自の型を作るやつです.
生JavaScript版, 型安全も何もない.
const { Record } = require("immutable");
class Person extends Record({ name: "", birthday: null }) {
get age() {
return new Date().getFullYear() - this.birthday.getFullYear();
}
年齢偽装() {
return this.set("birthday", new Date("1950-01-01"));
}
}
const ncaq = new Person({ name: "ncaq", birthday: new Date("1996-01-25") });
console.log(ncaq);
console.log(ncaq.name);
console.log(ncaq.set("name", "エヌユル"));
console.log(ncaq.age);
console.log(ncaq.年齢偽装());
実行結果
Person { name: "ncaq", birthday: Thu Jan 25 1996 09:00:00 GMT+0900 (JST) }
ncaq
Person { name: "エヌユル", birthday: Thu Jan 25 1996 09:00:00 GMT+0900 (JST) }
22
Person { name: "ncaq", birthday: Sun Jan 01 1950 09:00:00 GMT+0900 (JST) }
Flow版
Flow版はプロパティアクセスが使えません.
なのでget
メソッドを使ってアクセスすることになります.
文字列を間違えるとエラーが出ます.
Flowを使うの初めてだったので,
birthdayの初期値を設定しないでコンストラクト時に要求する方法がわかりませんでした.
// @flow
import { Record } from "immutable";
class Person extends Record({ name: "", birthday: new Date() }) {
get age() {
return new Date().getFullYear() - this.get("birthday").getFullYear();
}
年齢偽装() {
return this.set("birthday", new Date("1950-01-01"));
}
}
const ncaq = new Person({ name: "ncaq", birthday: new Date("1996-01-25") });
console.log(ncaq);
console.log(ncaq.name);
console.log(ncaq.set("name", "エヌユル"));
console.log(ncaq.age);
console.log(ncaq.年齢偽装());
TypeScript版
TypeScript版はプロパティアクセスが使えます.
勿論プロパティを間違えるとエラーです.
get
メソッドも使えますが,
Flow版とインターフェイスが違い,
notSetValue
引数を指定しないとget
できません.
import {Record} from 'immutable';
class Person extends Record({ name: "", birthday: null }) {
get age() {
return new Date().getFullYear() - this.birthday.getFullYear();
}
年齢偽装() {
return this.set("birthday", new Date("1950-01-01"));
}
}
const ncaq = new Person({ name: "ncaq", birthday: new Date("1996-01-25") });
console.log(ncaq);
console.log(ncaq.name);
console.log(ncaq.set("name", "エヌユル"));
console.log(ncaq.age);
console.log(ncaq.年齢偽装());
Immutable.js 4ではFlowでもTypeScriptでも型エラーを出してくれることがわかりました.
デフォルト値を設定せずにnullを排除しようと思ったけど思考が間違っていました
この章は思考が間違っているので読まなくて良いです.
どちらでもbirthday
にnull
を許可しないで,
初期値を設定せず,
コンストラクタで設定することを要求する方法はわかりませんでした.
TypeScriptではclass Person extends Record<{name: string, birthday: Date}>({ name: "", birthday: null })
みたいに書けることはわかりましたが,
"strictNullChecks": true
にしたら当然ですがbirthday: null
の表記に怒り出すんですよね.
かと言ってbirthday: null
を削除したら型が不一致になって怒られますし.
これは独自のコンストラクタを設置してそこで値を要求し,
デフォルト値は適当なものを入れておくしか無いのでしょうか?
使われないデフォルト値を設置するのも気が引けるのですが…
誰か教えてください.
これはnull
を許可したいという話ではなく,
null
を許可しないで,
なおかつユーザがコンストラクタに値を入力することで設定することを強制したいというものです.
例えば今回の例ではbirthday
はユーザが入力して意味のある値で,
これをクラス側が適当に現在時刻を入れてしまってはヘンなことになります.
普通のclassでは
class Person {
name: string;
birthday: Date;
constructor(name: string, birthday: Date) {
this.name = name;
this.birthday = birthday;
}
get age() {
return new Date().getFullYear() - this.birthday.getFullYear();
}
}
const ncaq = new Person("ncaq", new Date("1996-01-25") );
const errorNcaq = new Person("ncaq", null ); // strictNullChecksを有効にするとエラー
console.log(ncaq);
console.log(ncaq.name);
console.log(ncaq.age);
のように初期値を設定せずに非nullに出来るじゃないですか.
これをImmutable.jsのRecord
で実現したい.
removeやdeleteInを持つImmutable.jsでデフォルト値とnull排除を求めるのが間違っていると気がついた
よく考えたらremove
を備えるImmutable.jsのRecord
でこれを求めるというのがそもそも要件的に間違っていました.
Immutable.jsのRecord
のremove
はフィールドを削除するわけですが,
削除したフィールドは何になるかというとデフォルト値に戻るわけですね.
だからデフォルト値を設定せずにnull
を排除するのは無理です.
求めるものを間違っていたようですね.