Skip to content

Usage with TypeScript #1048

@stewartrule

Description

@stewartrule

Hi, I'm running into some issues when using hyperapp (^2.0.13) with typescript (^4.2.3).

I remember trying things about about 6 months ago and had similar experiences but thought maybe the definitions were not really ready yet.

I'm not sure if there are any guidelines into usage with ts, but I kind of feel the generics aren't always passed down properly. I wrote down some issues below.


No problems yet.

import { app, h, text, View } from "hyperapp";
import { state, State } from "./state";

const Canvas: View<State> = () => {
  return h("div", {}, [text("ok")]);
};

app<State>({
  init: state,
  view: Canvas,
  node: document.getElementById("app")!,
});

Introducing .map(toShape) suddenly causes a conflict.

// Type '(state: State) => VDOM<unknown>' is not assignable to type 'View<State>'.
// Type 'VDOM<unknown>' is not assignable to type 'VDOM<State>'.
const Canvas: View<State> = (state) => {
  return h("div", {}, state.shapes.map(toShape));
};

const toShape = (shape: ShapeType) => {
  return h("h3", {}, [text(shape.type)]);
};

app<State>({
  init: state,
  view: Canvas,
  node: document.getElementById("app")!,
});

Removing View<State> and just using (state: State) moves the error up to the app call.

import { app, h, text, View } from "hyperapp";
import { ShapeType, state, State } from "./state";

const Canvas = (state: State) => {
  return h("div", {}, state.shapes.map(toShape));
};

const toShape = (shape: ShapeType) => {
  return h("h3", {}, [text(shape.type)]);
};

app<State>({
  init: state,

  // Type '(state: State) => VDOM<unknown>' is not assignable to type 'View<State>'.
  // Call signature return types 'VDOM<unknown>' and 'VDOM<State>' are incompatible.
  view: Canvas,

  node: document.getElementById("app")!,
});

Passing State to every call to h seems to work, but I really don't want to do that.

import { app, h, text, View } from "hyperapp";
import { ShapeType, state, State } from "./state";

const Canvas = (state: State) => {
  return h<State>("div", {}, state.shapes.map(toShape));
};

const toShape = (shape: ShapeType) => {
  return h<State>("h3", {}, [text(shape.type)]);
};

app<State>({
  init: state,
  view: Canvas,
  node: document.getElementById("app")!,
});

The only thing that seems to work ok is wrapping the h call itself and just hardcode S to State but since I just started looking into this I'm not sure if this won't cause other issues later on.

import { PropList, MaybeVDOM, VDOM, h as ha } from "hyperapp";
import { State } from "./state";

type H = <T extends string = string>(
  tag: T extends "" ? never : T,
  props: PropList<State>,
  children?: MaybeVDOM<State> | readonly MaybeVDOM<State>[]
) => VDOM<State>;

export const h: H = (tag, props, children) => ha(tag, props, children);

Any ideas on how to use hyperapp properly when using typescript?

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionHow do I do that?typesStrings, numbers, booleans

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions