この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
TypeScript - TypeSafe な ArrayObject と 操作
TypeSafe な ArrayObject と ArrayObject の操作
を考えました(あまり実用的では有りません)
環境
VSCode バージョン1.36.1 (1.36.1)
TypeScript とは
型安全で開発可能な AltJS です
Microsoft が主体で開発しています
TypeSafe ではない ArrayObject
const serviceStatusDic = [
{ code: 100, label: "foo" },
{ code: 200, label: "bar" }
];
どのあたりが TypeSafe ではない?
object の key の typo がありえる
もう少し頑張る
object は 任意組み合わせ(ホワイトリスト) にしたい
- code が 100 の時は、label は foo
- code が 200 の時は、label は bar
TypeSafe な ArrayObject
VSCode の言語を TypeScript にして貼り付けてみてください
警告がでます ?
type TypeBase = {
code: number;
label: string;
};
class Foo implements TypeBase {
code!: 100;
label!: "foo";
}
class Bar implements TypeBase {
code!: 200;
label!: "bar";
}
type ServiceStatus = Foo | Bar;
const serviceStatusDic: Readonly<ServiceStatus[]> = [
{ code: 100, label: "foo" }, // OK
{ code: 200, label: "bar" }, // OK
{ cobe: 200, label: "bar" }, // cobe なので エラーになる
{ code: 300, label: "bar" }, // 300 なので エラーになる
{ code: 200, lightNovel: 'bar' }, // なろう系 なので エラーになる
{ code: 200, label: "f00" }, // オレでなきゃ 見逃しちゃうね
{ code: 100, label: "bar" } // 100 と bar の組み合わせ なので エラーになる
];
TypeSafe な ArrayObject 操作
VSCode の言語を TypeScript にして貼り付けてみてください
警告がでます ?
type Whitelist<T> = T[keyof T];
type WhitelistCode = Whitelist<Pick<ServiceStatus, "code">>;
type WhitelistLabel = Whitelist<Pick<ServiceStatus, "label">>;
const matchCode = (c: WhitelistCode) => (s: ServiceStatus) => s.code === c;
const _findMatchCodeFromServiceStatusDic = (c: WhitelistCode) =>
serviceStatusDic.find(matchCode(c));
const find = _findMatchCodeFromServiceStatusDic; // alias
// ---
find(100); // {code: 100, label: 'foo'}
find(200); // {code: 200, label: 'bar'}
find(999); // 999はエラーになる
const label100: WhitelistLabel = "foo";
const label200: WhitelistLabel = "bar";
const labelXxx: WhitelistLabel = "xxx"; // xxxはエラーになる
まとめ
別の回答もあるかもしれませんので、探してみてください
追加
Readonly
を DeepReadonly
に置き換えるさらに強固
// https://github.com/Microsoft/TypeScript/issues/13923#issue-205837616
type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
}