TypeScript – TypeSafe な ArrayObject と 操作
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]>; }