-
Notifications
You must be signed in to change notification settings - Fork 781
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 definitions for 2.0.10 #1016
Conversation
type StateWithEffects<S, D = any> = [State<S>, ...(Effect<S, D> | RunnerDescriptor<S, D>)[]] appears to permit the following usage import {delay} from @hyperapp/time
const MyAction = state => [state, delay] But as far as I know hyperapp does not support this, and will encounter a runtime error. |
The following tests represent valid uses of hyperapp, but fail with the current types. // -------------------------------------
// app with initial effect
import { delay } from '../../packages/time/index.js'
const IncrementFoo: Action<Test> = state => ({ ...state, foo: state.foo + 1 })
// $ExpectType void
app<Test>({
init: [{ foo: 2 }, delay(2000, { foo: 3 })],
view: state => h('main', {}, []),
node: document.body,
})
// $ExpectType void
app<Test>({
init: [{ foo: 2 }, delay(2000, IncrementFoo)],
view: state => h('main', {}, []),
node: document.body,
})
// $ExpectType void
app<Test>({
init: (state: Test) => [{ foo: 2 }, delay(200, IncrementFoo)],
view: state => h('main', {}, []),
node: document.body,
}) As far as I can tell, the reason they fail is because The error messages are:
|
@zaceno Nice work! I'll look at these later. |
@asabatba Your subscriptions example from #969 (comment) seems to expose a bug in my types. An important find indeed! I'll see what I can do. |
Well, const MyAction = state => [state, delay] is, in Hyperapp's eyes, equivalent to const MyAction = state => [(state) => state, delay] which is covered by the type definitions type Action<S, P = any> = ActionTransform<S, P> | ActionDescriptor<S, P>
type ActionTransform<S, P = any> = (state: State<S>, props?: Payload<P>) => StateFormat<S> | Action<S>
type StateFormat<S> = State<S> | StateWithEffects<S>
type StateWithEffects<S, D = any> = [State<S>, ...(Effect<S, D> | RunnerDescriptor<S, D>)[]] The key is |
@icylace You're mistaken I'm afraid.
and
are not equivalent to hyperapp. The former causes a runtime error while the latter does not, as evidenced by this live example |
@zaceno I love test cases ! |
Sorry I think I misunderstood you before. Like you were approving of my flems.io example.😅 I now think you meant: "please give me a test case that I can make work, or reject as being an invalid test case" ? If so, here's a failing test case. I believe the types should be altered so that it does not fail: import { Dispatch, Payload, Effect, Action } from "hyperapp"
type Test = { x: number; y: number }
const runJustEcho = (
_dispatch: Dispatch<Test>,
data?: Payload<string>
): void => {
console.log(data)
}
const justEcho: Effect<Test, string> = (x) => [runJustEcho, x]
/*
The following action definition is not valid
hyperapp. We would expect a type error.
However, the types as defined allow this
action definition. Hence this test
case fails
*/
// $ExpectError
const IncrXAndEcho: Action<Test> = (state: Test) => [
{ ...state, x: state.x + 1 },
justEcho
] UPDATE: Changing: type StateWithEffects<S, D = any> = [State<S>, ...(Effect<S, D> | RunnerDescriptor<S, D>)[]] to: type StateWithEffects<S, D = any> = [State<S>, ...RunnerDescriptor<S, D>[]] in the definition file fixes it. And breaks no other tests. |
@icylace Here's another test case that I would not expect to fail but does: // $ExpectType VDOM<unknown>
h("input", {oninput: (state, event) => event.target.value}) Error output:
I'm afraid I'm not good enough with TS yet to know wether the types should be improved, loosened or if the test itself needs to have some type annotations to pass. EDIT: This is a valid failure. My test should not pass without additional validation that the event target is not null, and casting the event.target to the expected type. Ignore this comment. |
Further findings about #1016 (comment) : It is because RunnerDescriptor is typed as a tuple: type RunnerDescriptor<S, D> = [Runner<S, D>, Payload<D>] However, the type-checker is unable to infer that The following is how the test could be made to work: import { h, app, Action, RunnerDescriptor } from "hyperapp"
import { delay } from "../../packages/time/index.js"
type Test = { foo: number; bar?: number }
const IncrementFoo: Action<Test> = state => ({ ...state, foo: state.foo + 1 })
// $ExpectType void
app<Test>({
init: [{ foo: 2 }, delay(200, IncrementFoo) as RunnerDescriptor<Test, any>], // <--- note "as RunnerD..."
view: state => h("main", {}, []),
node: document.body,
}) The same problem, and same approach would go for any action/event handler where an action with payload is needed: It would have to be cast to Seems like it could end up getting annoying... especially when using plain javascript as it requires using ————- Edit: you would only need to cast to a tuple in those cases where the function you are importing doesn’t have types. I assume that once this PR is merged we’ll go on to add types to all the @hyperapp/xyz libraries. So in practice it’s only a problem for javascripters who are making custom effects AND want to use typechecking. They will have to write some type annotations I JSDoc-comments to silence the type checker sometimes. Maybe not such a big deal - I think I could live with it anyway. |
I want to wait for this before going official, but just how close are we to merging here? Left you some comments, @icylace. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to remove all non-essential type tests, and put just the bare minimum in a single file.
I would agree that any redundant tests should be removed but what is a "non-essential" test? Why would you assume the bare minimum fits appropriately in a single file? |
I just one to merge |
Let's just merge |
I'm making updates soon which includes bug fixes and some renaming. |
Massive changes were made !!! Here's my changelog:
For now, I've decided to leave in certain "superfluous" but useful types, namely |
Wow @icylace, massive work! Look forward to digging in to the news! |
Thank you, @icylace! 💯 |
A new and improved TypeScript definitions PR !