natdm / typewriter

Synchronize your front-end models with your Go models
82 stars 5 forks source link

option to generate TypeScript interface rather than type #8

Open nilslice opened 6 years ago

nilslice commented 6 years ago

I am finding that it makes for a nicer workflow when I use interfaces rather than types to model data coming from a JSON xhr endpoint. My use case is closely aligned with Ponzu, for which I understand could be too specific to alter typewriter.

Here is my typical layout:

export interface ItemData {
    uuid: string;
    id: number;
    slug: string;
    timestamp: number;
    updated: number;
}

export interface VideoData extends ItemData {
    title: string;
    category: string;
    duration: number;
}

export class Item implements ItemData {
    uuid: string;
    id: number;
    timestamp: number;
    updated: number;
    slug: string;

    constructor(data: ItemData) {
        this.uuid = data.uuid;
        this.id = data.id;
        this.timestamp = data.timestamp;
        this.updated = data.updated;
        this.slug = data.slug;
    }

    // ... methods for inheritance by other classes
}

export default class Video extends Item {
    title: string;
    category: string;
    duration: number;

    constructor(data: VideoData) {
        super(data);

        this.title = data.title;
        this.category = data.category;
        this.duration = data.duration;
     }
}

I do this simply because having a class extend an Item seems to be the only way to get the class to inherit the values and methods.. If Item were a type, I don't see how I can gain the same level of inheritance (of properties or methods) between my classes that I do by using something like Item as a base class.

Again, I know this is unique to Ponzu and the situation where classes are tied directly to data coming in as JSON from a xhr call so it might be too specific. If you have any suggestions as to how I might be able to accomplish the same outcome as above by using the types generated by Typewriter, I would be happy to know!

The purpose of this issue is to see if there is a reason to extend Typewriter with a "generate interfaces" option, or if there is a better way for me to be structuring my client code.

Thanks for making Typewriter -- I've shared it with a number of folks asking about making web clients for Ponzu.

natdm commented 6 years ago

How would your code that generates this look like?

nilslice commented 6 years ago

:grimacing: sorry, I had my notifications off for a bit and this totally slipped by me.. the Go code would be a Ponzu content type, like so:

package content

import (
    "fmt"

    "github.com/ponzu-cms/ponzu/management/editor"
    "github.com/ponzu-cms/ponzu/system/item"
)

type Video struct {
    item.Item

    Title    string `json:"title"`
    Category string `json:"category"`
    Duration int    `json:"duration"`
}

func (v *Video) MarshalEditor() ([]byte, error) {
    view, err := editor.Form(v,
        editor.Field{
            View: editor.Input("Title", v, map[string]string{
                "label":       "Title",
                "type":        "text",
                "placeholder": "Enter the Title here",
            }),
        },
        editor.Field{
            View: editor.Input("Category", v, map[string]string{
                "label":       "Category",
                "type":        "text",
                "placeholder": "Enter the Category here",
            }),
        },
        editor.Field{
            View: editor.Input("Duration", v, map[string]string{
                "label":       "Duration",
                "type":        "text",
                "placeholder": "Enter the Duration here",
            }),
        },
    )

    if err != nil {
        return nil, fmt.Errorf("Failed to render Video editor view: %s", err.Error())
    }

    return view, nil
}

func init() {
    item.Types["Video"] = func() interface{} { return new(Video) }
}

func (v *Video) String() string {
    return fmt.Sprintf("Video: %s", v.UUID)
}