typewriter icon indicating copy to clipboard operation
typewriter copied to clipboard

option to generate TypeScript interface rather than type

Open nilslice opened this issue 8 years ago • 2 comments

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.

nilslice avatar Aug 07 '17 17:08 nilslice

How would your code that generates this look like?

natdm avatar Sep 03 '17 15:09 natdm

: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)
}

nilslice avatar Sep 21 '17 06:09 nilslice