Reputation: 2700
I'm in a codebase that uses typescript to share API interface contracts between server (express) and react). These shared types are organized into namespaces, and work well but can be a bit verbose in express.
For example:
// Shared API type in global file
export namespace GetRecordAPI {
export type PathParams = {
recordId: string;
};
export type RequestBody = {};
export type QueryParams = {
date: string;
};
export type Response = APIResponseValidation & {
record: RecordData;
};
}
// Express route controller
type GetRecordHandler = RequestHandler<
GetRecordAPI.PathParams,
GetRecordAPI.Response,
GetRecordAPI.RequestBody,
GetRecordAPI.QueryParams
>;
export const getRecord: GetRecordHandler = async (req, res, next) => {
// ...
};
The problem is that it becomes pretty verbose to construct the RequestHandler
for each express route controller. Since everything is organized consistently in namespaces, I'd really like to have a global typescript wrapper that stitches it all together by passing the namespace.
// Global helper
type ExpressHandler<T> = RequestHandler<T.PathParams, T.Response, T.RequestBody, T.QueryParams>;
// Express route controller
export const getRecord: ExpressHandler<GetRecordAPI> = async (req, res, next) => {
// ...
};
Is something like this even remotely possible? The react app uses each exported type within the namespace independently, so it would be ideal to keep this structure, for now.
Upvotes: 5
Views: 764
Reputation: 2610
I don't think this is possible. The namespace you declared is a special one and behaves differently from a common namespace. Usually, namespaces get transpiled into objects and can be used as value or for types. But this namespace only exports types, and types won't be transpiled and subsequently the namespace neither. Adding real values also wouldn't help since any type logic that displays all keys or similar won't affect the types since they are, after all, no real values.
Upvotes: 1