Skip to content

strict ts#190

Open
fanshi1028 wants to merge 14 commits intoseanhess:mainfrom
fanshi1028:main
Open

strict ts#190
fanshi1028 wants to merge 14 commits intoseanhess:mainfrom
fanshi1028:main

Conversation

@fanshi1028
Copy link
Contributor

No description provided.

@seanhess
Copy link
Owner

seanhess commented Feb 9, 2026

@fanshi1028 Thanks for submitting this. Did you run through all the examples to test?

I'm getting a couple Typescript errors on your branch. Can you fix please? Do we have a typescript version mismatch or somethign?

 ➜  hyperbole git:(fanshi1028) cd client
 ➜  client git:(fanshi1028) npx webpack
assets by status 24.4 KiB [cached] 11 assets
orphan modules 31.1 KiB [orphan] 9 modules
cacheable modules 43.5 KiB
  ./src/index.ts + 9 modules 41.2 KiB [built] [code generated]
  ./package.json 381 bytes [built] [code generated]
  ./node_modules/debounce/index.js 2.02 KiB [built] [code generated]

ERROR in /Users/seanhess/code/hyperbole/client/src/events.ts
./src/events.ts 219:11-17
[tsl] ERROR in /Users/seanhess/code/hyperbole/client/src/events.ts(219,12)
      TS2345: Argument of type 'HyperView | undefined' is not assignable to parameter of type 'HyperView'.
  Type 'undefined' is not assignable to type 'HyperView'.
ts-loader-default_e3b0c44298fc1c14
 @ ./src/index.ts 3:0-192 114:4-14 115:4-20 116:4-20 202:4-18 205:4-14 206:4-20 207:4-20 209:4-15 213:4-18 217:4-17 221:4-15 225:4-20 229:4-16 237:4-15

ERROR in /Users/seanhess/code/hyperbole/client/src/index.ts
44:2-17
[tsl] ERROR in /Users/seanhess/code/hyperbole/client/src/index.ts(44,3)
      TS2322: Type 'Timeout' is not assignable to type 'number'.
ts-loader-default_e3b0c44298fc1c14

webpack 5.89.0 compiled with 2 errors in 891 ms

@fanshi1028
Copy link
Contributor Author

@fanshi1028 Thanks for submitting this. Did you run through all the examples to test?

I'm getting a couple Typescript errors on your branch. Can you fix please? Do we have a typescript version mismatch or somethign?

 ➜  hyperbole git:(fanshi1028) cd client
 ➜  client git:(fanshi1028) npx webpack
assets by status 24.4 KiB [cached] 11 assets
orphan modules 31.1 KiB [orphan] 9 modules
cacheable modules 43.5 KiB
  ./src/index.ts + 9 modules 41.2 KiB [built] [code generated]
  ./package.json 381 bytes [built] [code generated]
  ./node_modules/debounce/index.js 2.02 KiB [built] [code generated]

ERROR in /Users/seanhess/code/hyperbole/client/src/events.ts
./src/events.ts 219:11-17
[tsl] ERROR in /Users/seanhess/code/hyperbole/client/src/events.ts(219,12)
      TS2345: Argument of type 'HyperView | undefined' is not assignable to parameter of type 'HyperView'.
  Type 'undefined' is not assignable to type 'HyperView'.
ts-loader-default_e3b0c44298fc1c14
 @ ./src/index.ts 3:0-192 114:4-14 115:4-20 116:4-20 202:4-18 205:4-14 206:4-20 207:4-20 209:4-15 213:4-18 217:4-17 221:4-15 225:4-20 229:4-16 237:4-15

ERROR in /Users/seanhess/code/hyperbole/client/src/index.ts
44:2-17
[tsl] ERROR in /Users/seanhess/code/hyperbole/client/src/index.ts(44,3)
      TS2322: Type 'Timeout' is not assignable to type 'number'.
ts-loader-default_e3b0c44298fc1c14

webpack 5.89.0 compiled with 2 errors in 891 ms

Oops. I just tsc-ed it and didn't even try to build with webpack. But I have just fixed them for webpack build and checked to ensured the demo app's examples do works. Please check again.

Copy link
Owner

@seanhess seanhess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this!

export function listenBubblingEvent(event: string, cb: (_target: HyperView, action: string) => void): void {
document.addEventListener(event, function(e) {
let el = e.target as HTMLInputElement
if (!(e.target instanceof HTMLElement)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary? HyperView extends HTMLElement. Perhaps this belongs at the callsite (or perhaps it already has a check there).

Either way, we shouldn't return without a console error

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theoretically some third party code could do thing like this:

document.addEventListener("click", function(e){
    if (e.target instanceof HTMLElement) {
        console.log(e)
    } else console.error("event target is not a HTMLElement %o", e)
})

document.dispatchEvent(new Event("click"))

The event's target will be null and break the original code.

No checking on the call site of listenBubblingEvent could ever prevent this.

In practice though, maybe no one will ever do this.

Copy link
Contributor Author

@fanshi1028 fanshi1028 Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if someone really dispatch their own event like this, whatever spaghetti they are into, it is their own business. Then when our handlers eavesdrop and catch them, this doesn't look like an "error" to me, so I just chose to ignored them in the code. But I think we can also warn them if you think we should, so I pushed a commit to "console.warn" about them now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tell me what you think. If you still think these checks are unnecessary(as it is really kind of a niche edge case). We could revert them all back to simple as HTMLElement.

let onMouseEnter = node.dataset.onmouseenter

let target = nearestTarget(node)
let target = nearestNonHyperViewTarget(node)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could theoretically still be a hyper view? I think we mean that it isn't required to be a HyperView.

Perhaps rename nearestTarget to nearestHyperViewTarget and rename this to nearestAnyTarget?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed

export function listenChange(cb: (target: HyperView, action: string) => void): void {
document.addEventListener("change", function(e) {
let el = e.target as HTMLElement
if (!(e.target instanceof HTMLElement)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above. Seems redundant

document.addEventListener("input", function(e) {
let el = e.target as HTMLElement
let source = el.closest("[data-oninput]") as LiveInputElement
if (!(e.target instanceof HTMLElement)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above. Seems redundant

if (!source) return

let delay = parseInt(source.dataset.delay) || 250
let delay = parseInt(source.dataset.delay || "") || 250
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, does parseInt(x) || 250 fail on undefined?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never. But we needs this unnecessary effort to please the compiler. parseInt take a string there.

console.error("Missing target: listenChange")
return
}
if (source.dataset.onchange === undefined) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplify to if (!source.dataset.onchange) like you did for oninput

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

export function listenFormSubmit(cb: (target: HyperView, action: string, form: FormData) => void): void {
document.addEventListener("submit", function(e) {
let form = e.target as HTMLFormElement
if (!(e.target instanceof HTMLFormElement)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, seems redundant

}

function nearestTarget(node: HTMLElement): HTMLElement {
function nearestTarget(node: HTMLElement): HyperView | undefined {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See notes above about renaming this and nearestNonHyperViewTarget

@@ -0,0 +1,15 @@
import { type Request } from "./action";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move enrichHyperViews to this module? Plus anything else that's directly related to this interface.

Copy link
Contributor Author

@fanshi1028 fanshi1028 Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we do that. We are moving almost all code in index.ts into it. As the code and quite tightly tangled together. enrichHyperViews need runAction. and runAction need the sock and its initialisation logic.

Here are some ways I imagine we can do about it.

  1. Just move it all. (Moving those initialisation code from index.ts into it doesn't feel right to me, but you tell me).
  2. Just move enrichHyperViews and make it take and an extra param "runAction".
  3. move the hyperView.ts code into event.ts (as only index.ts and event.ts import it)
  4. Don't move it and keep it as is.
  5. (Tell me if you have any other prefered solution)

I have chosen to do 2. Tell me it you prefer to do it other way.


// Should we connect to the socket or not?
const sock = new SocketConnection()
sock.connect()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we connect the socket? Does it happen automatically?

Copy link
Contributor Author

@fanshi1028 fanshi1028 Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I somehow moved it into the constructor, but now that I think about it, yup, I moved it back out.

@fanshi1028
Copy link
Contributor Author

fanshi1028 commented Mar 7, 2026

@seanhess Please check my replies and changes and tell me what to do next(if any).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants