Skip to content

cbain.tech

clbain93@gmail.com

Menu
Menu

Hyland software

Posted on August 19, 2025 by cbain

While working on the manufacturing floor at Beckett Gas, I was looking for an IT job. My expertise is in programming. The main languages I use are C, C++, C#, D and Javascript/Typescript.

Before coming to Hyland for an interview, I built a private web panel in D, Javascript and Typescript. It communicates with another server and manages actions to execute for users.

I decided to use Typescript for this project and created something special just for this. The following is a type-safe reducer creator written specifically for the version of the language out at the time.

// tslint:disable:prefer-object-spread
// tslint:disable:no-object-literal-type-assertion
// Action Types

import { connect } from 'react-redux';

type EmptyAction<T extends string> = {
    type: T;
};

type PayloadAction<T extends string, P> = {
    type: T;
    payload: P;
    error?: boolean;
};

type MetaAction<T extends string, P, M> = {
    type: T;
    payload: P;
    meta: M;
    error?: boolean;
};

type Action<T extends string, P = {}, M = {}> = EmptyAction<T> | PayloadAction<T, P> | MetaAction<T, P, M>;

// Action Creator Types

interface BaseActionCreator<T extends string> {
    actionName: T;
    toString: () => T;
}

interface EmptyActionCreator<T extends string> extends BaseActionCreator<T> {
    (): EmptyAction<T>;
    type: EmptyAction<T>;
}

interface PayloadActionCreator<T extends string, P> extends BaseActionCreator<T> {
    (payload: P): PayloadAction<T, P>;
    type: PayloadAction<T, P>;
}

interface OwnPayloadActionCreator<T extends string, P> extends BaseActionCreator<T> {
    type: PayloadAction<T, P>;
}

interface MetaActionCreator<T extends string, P, M> extends BaseActionCreator<T> {
    (payload: P, meta: M): MetaAction<T, P, M>;
    type: MetaAction<T, P, M>;
}

interface OwnMetaActionCreator<T extends string, P, M> extends BaseActionCreator<T> {
    type: MetaAction<T, P, M>;
}

type ActionCreator<T extends string, P, M> = EmptyActionCreator<T> |
                                            PayloadActionCreator<T, P> |
                                            OwnPayloadActionCreator<T, P> |
                                            MetaActionCreator<T, P, M> |
                                            OwnMetaActionCreator<T, P, M>;

type OwnPayloadBuilderFunction<T extends string, P> = <
    F extends (...a: any[]) => PayloadAction<T, P>
>(func: F) => OwnPayloadActionBuilder<T, P, F>;

type OwnMetaBuilderFunction<T extends string, P, M> = <
    F extends (...a: any[]) => MetaAction<T, P, M>
>(func: F) => OwnMetaActionBuilder<T, P, M, F>;

type EmptyActionBuilder<T extends string> = {
    payload: <P>() => PayloadActionBuilder<T, P>;
    meta: <P, M>() => MetaActionBuilder<T, P, M>;
    ownPayload: <P>() => OwnPayloadBuilderFunction<T, P>;
    ownMeta: <P, M>() => OwnMetaBuilderFunction<T, P, M>;
    to: EmptyActionCreator<T>;
};

type PayloadActionBuilder<T extends string, P> = {
    to: PayloadActionCreator<T, P>;
};

type OwnPayloadActionBuilder<T extends string, P, F> = {
    to: F & OwnPayloadActionCreator<T, P>;
};

type MetaActionBuilder<T extends string, P, M> = {
    to: MetaActionCreator<T, P, M>;
};

type OwnMetaActionBuilder<T extends string, P, M, F> = {
    to: F & OwnMetaActionCreator<T, P, M>;
};

type ActionBuilder<T extends string, P, M, F> = EmptyActionBuilder<T> |
                                            PayloadActionBuilder<T, P> |
                                            OwnPayloadActionBuilder<T, P, F> |
                                            MetaActionBuilder<T, P, M> |
                                            OwnMetaActionBuilder<T, P, M, F>;

export type ActionUnion<
    T extends { [k: string]: ActionCreator<any, any, any> },
    K extends keyof T = keyof T,
> = T[K]['type'];

export function action<T extends string, P, M>(type: T): EmptyAction<T>;
export function action<T extends string, P, M>(type: T, payload: P): PayloadAction<T, P>;
export function action<T extends string, P, M>(type: T, payload: P, meta: M): MetaAction<T, P, M>;
export function action<T extends string, P, M>(type: T, payload?: P, meta?: M): Action<T, P, M> {
    if (meta) {
        if (payload instanceof Error) {
            return ({ type, payload, meta, error: true });
        } else {
            return ({ type, payload, meta });
        }
    } else if (payload) {
        if (payload instanceof Error) {
            return ({ type, payload, error: true });
        } else {
            return ({ type, payload });
        }
    } else {
        return ({ type });
    }
}

export const actionCreator = <T extends string>(type: T): EmptyActionBuilder<T> => {
    return Object.assign(
            (): EmptyAction<T> => action(type),
            {
                payload: <P>(): PayloadActionBuilder<T, P> => {
                    return Object.assign(
                        (payload: P): PayloadAction<T, P> => action(type, payload),
                        {
                            to: undefined as any as PayloadActionCreator<T, P>,
                            actionName: type,
                            toString: () => type,
                            type: undefined as any as PayloadAction<T, P>
                        }
                    );
                },
                ownPayload: <P>(): OwnPayloadBuilderFunction<T, P> => {
                    return <F extends (...a: any[]) => PayloadAction<T, P>>(func: F) => {
                        return Object.assign(
                            func,
                            {
                                to: undefined as any as F & OwnPayloadActionCreator<T, P>,
                                actionName: type,
                                toString: () => type,
                                type: undefined as any as PayloadAction<T, P>
                            }
                        );
                    };
                },
                meta: <P, M>(): MetaActionBuilder<T, P, M> => {
                    return Object.assign(
                        (payload: P, meta: M): MetaAction<T, P, M> => action(type, payload, meta),
                        {
                            to: undefined as any as MetaActionCreator<T, P, M>,
                            actionName: type,
                            toString: () => type,
                            type: undefined as any as MetaAction<T, P, M>
                        }
                    );
                },
                ownMeta: <P, M>(): OwnMetaBuilderFunction<T, P, M> => {
                    return <F extends (...a: any[]) => MetaAction<T, P, M>>(func: F) => {
                        return Object.assign(
                            func,
                            {
                                to: undefined as any as F & OwnMetaActionCreator<T, P, M>,
                                actionName: type,
                                toString: () => type,
                                type: undefined as any as MetaAction<T, P, M>
                            }
                        );
                    };
                },
                to: {} as EmptyActionCreator<T>,
                actionName: type,
                toString: () => type,
                type: {} as EmptyAction<T>
            }
    );
};

const isBaseBuilder = <T extends string>(
    builder: ActionBuilder<T, any, any, any>
): builder is EmptyActionBuilder<T> => {
    return (builder as any).payload != null;
};

export const createActionTable = <
    T extends {
        [k: string]: ActionBuilder<any, any, any, any>
    },
    K extends keyof T = keyof T
>(
    table: T
): {[P in keyof T]: T[P]['to']} => {
    Object.values(table).forEach(obj => {
        if (isBaseBuilder(obj)) {
            delete obj.payload;
            delete obj.ownPayload;
            delete obj.meta;
            delete obj.ownMeta;
            delete obj.to;
        } else {
            delete obj.to;
        }
    });
    return table as any as {[P in keyof T]: T[P]['to']};
};

// STORE UTILS

export type Dispatch<STORE> = {
    <R>(async: (dispatch: Dispatch<STORE>, getState?: () => STORE) => R): R
    (action: Action<any, any, any>): void;
};

export const connectFactory = <STORE>() => {

    return ({
        sfcConnect: <PROPS>() => <STATE, DISPATCH>(
            mapStateToProps: (state: STORE, props?: PROPS) => STATE,
            mapDispatchToProps?: DISPATCH | ((dispatch: Dispatch<STORE>, props?: PROPS) => DISPATCH)
        ) => (component: React.SFC<PROPS & STATE & DISPATCH>) => {
            return connect(mapStateToProps, mapDispatchToProps as any)(component) as any as React.SFC<PROPS>;
        },
        classConnect: <PROPS>() => <STATE, DISPATCH>(
            mapStateToProps: (state: STORE, props: PROPS) => STATE,
            mapDispatchToProps?: DISPATCH | ((dispatch: Dispatch<STORE>, props: PROPS) => DISPATCH)
        ) => ({
            propsType: {} as PROPS & STATE & DISPATCH,
            connect: (component: React.ComponentClass<PROPS & STATE & DISPATCH>) =>
                connect(mapStateToProps, mapDispatchToProps as any)(component) as any as React.ComponentClass<PROPS>
        })
    });
};

I’ll finish this post later and add in some more details. I want to take a screenshot of what this actually allows for in the IDE.

Leave a Reply Cancel reply

You must be logged in to post a comment.

Recent Posts

  • No life
  • My job
  • Verizon wireless
  • Kia montrose
  • Reconstruction; vultr

Recent Comments

No comments to show.

Archives

  • August 2025
  • July 2025
  • June 2025
  • May 2025
  • April 2025
  • March 2025

Categories

  • Uncategorized
© 2025 cbain.tech | Powered by Minimalist Blog WordPress Theme