#How to share interfaces and classes from backend to frontend

9 messages · Page 1 of 1 (latest)

spark inlet
#

Hello,
I saw something related to .d.ts files but is it good way to do it
or there is another way ?

small surge
#

@spark inlet You can indeed create declarative files in TypeScript, publish them as a npm module and install this module in any of your applications.

Nonetheless, you should be aware that there are often some slight differences between how objects are used from a side to another.
These slight differences may make you reconsider the option of creating an entire module to share these types.

But some objects are worth being put in such module. I'm thinking DTOs for instance. Really dumb objects.
Rich behavior objects such as domain classes might need further analysis.

Of course it's my own opinion.

spark inlet
grizzled anchor
#

If you're in a monorepo, the easiest thing to do is use import type from the BE file. That way TS will still check the types, but the import won't end up in the compiled bundle at all.

hasty sorrel
#

I've come up with (with the help of OSS) a totally different take to getting types shared between frontend and backend with GraphQL.

The DX is very advanced and I would consider excellent. 😊

All the dev has to do is create her graphql query or mutation in a gql file for her frontend Vue component (i.e. the data or data manipulation she needs) and the code generation process, which uses the graphql introspection API, creates not only the types necessary, but also the useQueryFoo or useMutationBar methods to be directly used in the component. Here is an example of a "hello world" query.

#
import * as Types from '../../graphql/index';

import { computed as vueComputed } from 'vue';
import { useQuery as vueApolloUseQuery, useLazyQuery as vueApolloUseLazyQuery } from '@vue/apollo-composable';
import type * as VueApolloQuery from '@vue/apollo-composable/dist/useQuery';
import type { UseQueryReturn as VueApolloUseQueryReturn } from '@vue/apollo-composable';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
export type HelloWorldQueryVariables = Types.Exact<{ [key: string]: never; }>;


export type HelloWorldQuery = { __typename?: 'Query', helloWorld: string };


export const HelloWorldDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"helloWorld"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"helloWorld"}}]}}]} as unknown as DocumentNode<HelloWorldQuery, HelloWorldQueryVariables>;
export function useHelloWorldQuery(
  variables: VueApolloQuery.VariablesParameter<HelloWorldQueryVariables> = {},
  options: VueApolloQuery.OptionsParameter<HelloWorldQuery, HelloWorldQueryVariables> = {},
) {
  const useQuery = vueApolloUseQuery(HelloWorldDocument, variables, options);
  return {
    ...useQuery,
    helloWorld: vueComputed(() => useQuery.result.value?.helloWorld),
  };
}

export function useHelloWorldLazyQuery(
  variables: VueApolloQuery.VariablesParameter<HelloWorldQueryVariables> = {},
  options: VueApolloQuery.OptionsParameter<HelloWorldQuery, HelloWorldQueryVariables> = {},
) {
  return vueApolloUseLazyQuery(HelloWorldDocument, variables, options);
}

export type HelloWorldCompositionFunctionResult = VueApolloUseQueryReturn<HelloWorldQuery, HelloWorldQueryVariables>;
vale jay
#

As @grizzled anchor mentioned, a monorepo is the best option for this problem, and I don't suggest publishing to npm at all, it's gonna be a bad dx specially if you're working with multiple devs, on multiple features, on multiple branches ... etc.

uncut hinge
#

Maybe this could be solution also for you: In my last projects I used swagger on the backend (what is super easy with nest) and „orval“ on my react-frontend to generate my api-client. It works really well.

spark inlet