thi-ng / umbrella

⛱ Broadly scoped ecosystem & mono-repository of 199 TypeScript projects (and ~180 examples) for general purpose, functional, data driven development
https://thi.ng
Apache License 2.0
3.35k stars 149 forks source link

[hiccup-svg] typing for PathSegments #360

Closed pcace closed 1 year ago

pcace commented 1 year ago

Hi there, is there any chance to get a typing for PathSegments (IHiccupPathSegment, https://github.com/thi-ng/umbrella/blob/b05cfcb53218a6ff8a75bc0ff0516629e70d531f/packages/geom-api/src/path.ts#L19)

if i have an object like this (segment: PathSegment):

{
    "type": "l",
    "geo": {
        "points": [
            [
                -41.24092863081023,
                -21.321117777377367
            ],
            [
                -72.80925072683021,
                -17.69912462029606
            ]
        ]
    }
}

it should be technically correct, but trying to use it for example like this: segment.geo.points.map(x => [x[0], -x[1]]) it gives me this typing error:

Property 'points' does not exist on type 'IShape<IShape<any>> & IHiccupPathSegment'.ts(2339)

but it should be there shouldn't it?

Cheers and thanks!

postspectacular commented 1 year ago

I'm not 100% sure what you're asking for, since there're 2 flavors of hiccup for shapes and your title refers to one (hiccup-svg), but your code snippets to the other (i.e. that one used by thi.ng/geom & thi.ng/hiccup-canvas). You can find more details & reasons for these differences in the hiccup-canvas readme.

For that geom version, if you're after a mapped type to identify the actual IShape type for a path segment's geo, then maybe this could help:

import type { Arc, Cubic, Line, Quadratic } from "@thi.ng/geom";
import type { SegmentType } from "@thi.ng/geom-api";

export interface PathSegmentMap {
    a: Arc;
    c: Cubic;
    l: Line;
    q: Quadratic;
}

export type PathSegmentShape<T extends SegmentType> =
    T extends keyof PathSegmentMap ? PathSegmentMap[T] : undefined;

With that you can derive concrete shape types via e.g. PathSegmentShape<"c"> for cubic segments or PathSegmentShape<"l"> for lines...

Be aware that only c, l and q segment shape types will contain a points array to map over, arc segments don't. So a guard for the .geo.points property is required somewhere in your code. Also, (just FYI) the kind of transformation you're doing (i.e. x => [x[0], -x[1]]) can be directly achieved via the geom package's built-in operators, e.g. scale(myPath, [1, -1]) or use transform() for more complex matrix-based transformations.

pcace commented 1 year ago

Hi, thank you so much for your reply! and thanks also for all the additional information! It completely worked - sorry for that question, i am not yet too familiar with TypeScript and thi.ng.

Cheers and thanks!