結
起
NativeScriptのObservableは、プロパティへの代入(っぽいメソッド)から、処理をフックすることができるクラスです。 MVVMパターンとかに使えます。 (って公式が言ってた。)
しかしこのObservableにはやばい欠陥があって、上記リンクを見てもらえればわかるのですが、代入と取得(に対応するメソッド)の型が忘却されちゃってます。
export class Observable {
// ...
// vvv
get(name: string): any
// vvv
set(name: string, value: any): void
// ...
}
え、any
……? あっ、あたなは最低です! 静的型付けをなんだと思っているのですか!
結
TypeScriptの型付けはめっちゃ考えられているので、型引数で情報を渡してあげるだけで、それに対する安全なget/set
の型を導出してあげられます。 ただしsuper
の最低なget/set
をなかったことにはできないので、deprecatedにしておいて、新しくassign/take
というのを定義してあげることにします。 (このdeprecated-decorator
は、そのメソッドが実行時に使用された際に、メッセージをコンソールに出力するものなので、静的なものではないようです。注意。)
ヘルパー型さん 1
/**
* Declare a type T of a property K via K of a type X.
*
* - Field<{foo: number, bar: string}, 'foo', number> = 'foo'
* - Field<{foo: number, bar: string}, 'bar', string> = 'bar'
* - Field<{foo: number, bar: string}, 'foo', string> = never
*/
type Field<X, K extends string, T> = K extends keyof X
? T extends X[K] ? K : never
: never
冒涜的でないObservable 2
/**
* Don't dirty your hands.
* You must use this instead of [[Untyped.Observable]].
*/
export default class Observable<X extends object> extends Untyped.Observable {
constructor() {
super()
}
/**
* A typed safety set()
*/
public assign<K extends string, T>(name: Field<X, K, T>, value: T): void {
super.set(name, value)
}
@deprecated('assign')
public set(name: string, value: any): void {
super.set(name, value)
}
/**
* A type safety get()
*/
public take<K extends string, T>(key: Field<X, K, T>): T | undefined {
return super.get(key)
}
@deprecated('take')
public get(name: string): any {
super.get(name)
}
}
チェックしてみる。
const p = new Observable<{ x: number, y: string }>()
p.assign('x', 10)
p.assign('y', 'poi')
// 2345: Argument of type '"y"' is not assignable to parameter of type 'never'.
// p.assign('y', 10)
const x: number = p.take('x')
const y: string = p.take('y')
// 2345: Argument of type '"y"' is not assignable to parameter of type 'never'.
// const e: number = p.take('y')
OK!!!
コード全文はこちら 👇
TypeScriptのconditional typesは初めてだったので、いい型慣らし肩慣らしになったと思います。 TypeScriptに型を付けてもらうのではなく、TypeScriptで型を付けにいく側にまわった気分はどうだ?
See you next time 👋
この記事はこちらから修正リクエストを送ることができます。
NativeScriptの型不安全なObservableを型安全にする - github
ゴミ箱ボタンの左にある、鉛筆ボタンを押してね!