javascripttypescriptx-tag

How would you define the Typescript interface signature for an x-tag component


The x-tag spec has the following signature in pure JS -

xtag.register('x-accordion', {
    // extend existing elements
    extends: 'div',
    mixins: ['superdefaults', 'otherdefaults'],
    lifecycle:{
        created: function(){
            // fired once at the time a component
            // is initially created or parsed
        },
        inserted: function(){
            // fired each time a component
            // is inserted into the DOM
        },
        removed: function(){
            // fired each time an element
            // is removed from DOM
        },
        attributeChanged: function(){
            // fired when attributes are set
        }
    },
    events: {
        'click:delegate(x-toggler)': function(){
            // activate a clicked toggler
        }
    },
    accessors: {
        'togglers': {
            get: function(){
                // return all toggler children
            },
            set: function(value){
                // set the toggler children
            }
         }
    },
    methods: {
        nextToggler: function(){
            // activate the next toggler
        },
        previousToggler: function(){
            // activate the previous toggler
        }
    }
});

Where obviously methods, accessors, and events can have multiple entries.

I am trying to define the Typescript equivalent of the object literal that is passed to the register function. Anyone have any ideas how to achieve this?


Solution

  • The secret for methods, accessors, and events is using a string indexer. I was only going to write that part but that ended up being most of it anyways, so I finished it off.

    declare module xtag {
        interface RegisterParams {
            extends?: string;
            prototype?: any;
            mixins?: string[];
            lifecycle?: {
                created?: () => void;
                inserted?: () => void;
                removed?: () => void;
                attributeChanged?: () => void;
            }
            events: { [name: string]: () => void; };
            accessors: {[name: string]: {
                get?: () => any;
                set?: (value: any) => any;
                attribute?: any;
            }};
            methods: { [name: string]: () => void; }
        }
        export function register(tagName: string, params: RegisterParams): void;
    }
    

    There's a decent explanation of indexers here. On accessors there's no way to express that get and set are mutually exclusive with attribute. The best we can do there is make them optional.