-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
typescript version of store #2733
Conversation
This looks great, thank you. If the store.d.ts file is auto-generated, should it be excluded from the repo, or is it better to have it here? |
The store.d.ts is derived, so it's probably better to remove the file. Wasn't sure when to generate them, so now doing it in the prepare script. Also added the cleanup for derived, but had some trouble typechecking result variable (added |
The last commits extends the |
Thanks — we've avoided having a |
Removed the commits :) |
The current implementation of |
One problem surfaces when converting the test |
That's a good point. Should we even have an initial value for a derived? It gets overwritten synchronously anyway. |
|
The current interface of derived is especially difficult for a type specification, because the source stores can have their own types (T1, ..., Tn). These types should become types of the parameters of the callback function |
Although Typescript could use some extra goodness in the type-system, we actually can represent those types already: type Stores = Readable<any> | [Readable<any>, ...Readable<any>[]]
type StoresValues<T> = T extends Readable<infer U> ? U :
{ [K in keyof T]: T[K] extends Readable<infer U> ? U : never }
declare function derived<T, S extends Stores>(
stores: S,
fn: (values: StoresValues<S>) => void,
initial_value?: T
): Readable<T>; This will type check all combinations of const a = writable(0)
const b = writable('string')
const c = writable({ object: 1 })
const d = 0
derived(a, (a) => {})
// derived(stores: Writable<number>,
// fn: (values: number) => void,
// initial_value?: {}): Readable<{}>
derived([a], ([a]) => {})
// derived(stores: [Writable<number>],
// fn: (values: [number]) => void,
// initial_value?: {}): Readable<{}>
derived([a, b, c], ([a, b, c]) => {})
// derived(stores: [Writable<number>, Writable<string>, Writable<{object: number}>],
// fn: (values: [number, string, {object:number}] => void,
// initial_value?: {}): Readable<{}>
derived(a, ([a]) => {}) // errors on second argument
derived([a], ([a, b]) => {}) // errors on second argument
derived([a, b, c, d], ([a, b, c, d]) => {}) // errors on first argument, d is a number
// doesn't error but infers a = [number]
derived([a], (a) => {})
// unfortunately doesn't error, it's just a valid regular js partial
// destructuring so nothing the type system could do
derived([a, b], ([a]) => {}) (I omitted |
Wow that is pretty advanced type juggling :) Removing strict checking hides the error for initial value, so maybe that is better for now. |
man, some of this TS stuff goes way over my head. thanks! |
Added types in the
store.ts
without changing any function signatures/implementation details. The rollup generates the javascript versions of the store. Added atsd
script that generates the interface definition for the store. The interface definitions are at the moment committed in the repository.