Skip to content
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

Constrain typescript definitions #49

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

Erikvv
Copy link

@Erikvv Erikvv commented Jun 17, 2018

Provides better type safetly by forwarding the types of the hyperscript implementation to the helper.

The types put some constraints in place that the actual code doesn't:

  1. The generated helpers have 3 arguments (this is already the case in the current typings)
  2. argument "attributes" comes before "children"
  3. attributes and children are constrained (but sensibly so I would say)

2 and 3 restrict both the hyperscript implementation and the generated helpers

I tried to get rid of these assumptions by "forwarding" the types entirely from the hyperscript implementation.
Unfortunately I'm either not smart enough to make that work or it's not possible.

Below is how far I got using that approach. It works in a few cases but R1 and R2 are too restricted somehow. When I add R3 things get more messed up.

/**
 * The minimal featureset the hyperscript implementation should support
 */
declare interface HyperScriptFn<Element, Tag, R1, R2> {
  (tag: Tag, r1?: R1, r2?: R2): Element;
}

/**
 * The actual hyperscript-helper function
 * The purpose of hyperscript-helpers is so you can use this function
 */
declare interface HyperScriptHelperFn<
  H extends HyperScriptFn<any, any, any, any>,
  Element = H extends HyperScriptFn<infer Element, any, any, any> ? Element : never,
  R1 = H extends HyperScriptFn<any, any, infer R1, any> ? R1 : never,
  R2 = H extends HyperScriptFn<any, any, any, infer R2> ? R2 : never
> {
  (selector: string, r1?: R1, r2?: R2): Element;
  (r1?: R1, r2?: R2): Element;
}

/**
 * Map of the actual helper functions generated by hh()
 */
declare type HyperScriptHelpers<H extends HyperScriptFn<any, any, any, any>> = {
  [key in (keyof HTMLElementTagNameMap | 'svg')]: HyperScriptHelperFn<H>;
}

export default function hh<
  H extends HyperScriptFn<any, any, any, any>,
>(h: H): HyperScriptHelpers<H>;

@Erikvv
Copy link
Author

Erikvv commented Jun 18, 2018

I gave it another shot to get rid of the overly strict requirements on the hyperscript implementation.

And it looks I succeeded!

Unfortunately I seem to run into the typescript issue below which makes it so that the hyperscript implementation can't have any overloads.

microsoft/TypeScript#13570

This is a deal-breaker because the implementations need the overloads for correctness.

So looks like the current commit is as good as it gets unfortunately.

@hellos3b
Copy link

hellos3b commented Apr 7, 2021

Support for this would be great

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