Skip to content

Instantly share code, notes, and snippets.

@aiya000
Last active July 8, 2019 05:15
Show Gist options
  • Save aiya000/5f12ca0276eabaf6bf1331ee2cd96fae to your computer and use it in GitHub Desktop.
Save aiya000/5f12ca0276eabaf6bf1331ee2cd96fae to your computer and use it in GitHub Desktop.
Typgin NativeScript's untyped Observable
import * as Untyped from 'tns-core-modules/data/observable'
import deprecated from 'deprecated-decorator' // npm install --save-dev deprecated-decorator
/**
* ValueTypes<{foo: number, bar: string}> = number | string
*/
type ValueTypes<T> = T extends { [k: string]: infer I }
? I
: never
/**
* Field<'foo', {foo: number, bar: string}> = 'foo'
*/
type Field<X, K extends string, T> = K extends keyof X
? X[K] extends T ? K : never
: never
/**
* 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 {
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')
// Use {x?: number, y?: string} if you are careful to forget initializing :D
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment