How to use TypeScript with AppSync Lambda Resolvers

Prerequisites

type Query {
post(id: ID!): Post
}
type Mutation {
createPost(post: PostInput!): Post!
}
type Post {
id: ID!
title: String!
content: String!
publishedAt: AWSDateTime
}
input PostInput {
title: String!
content: String!
}

Setting up the project

Install the dependencies

npm i @graphql-codegen/cli @graphql-codegen/typescript @types/aws-lambda  -D

Create the configuration file

overwrite: true
schema:
- schema.graphql #your schema file
generates:
appsync.d.ts:
plugins:
- typescript

Support for AWS Scalars

scalar AWSDate
scalar AWSTime
scalar AWSDateTime
scalar AWSTimestamp
scalar AWSEmail
scalar AWSJSON
scalar AWSURL
scalar AWSPhone
scalar AWSIPAddress
schema:
- schema.graphql
- appsync.graphql # 👈 add this
# and this 👇
config:
scalars:
AWSJSON: string
AWSDate: string
AWSTime: string
AWSDateTime: string
AWSTimestamp: number
AWSEmail: string
AWSURL: string
AWSPhone: string
AWSIPAddress: string

Generate the code

graphql-codegen
export type Maybe<T> = T | null;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
ID: string;
String: string;
Boolean: boolean;
Int: number;
Float: number;
AWSDate: string;
AWSTime: string;
AWSDateTime: string;
AWSTimestamp: number;
AWSEmail: string;
AWSJSON: string;
AWSURL: string;
AWSPhone: string;
AWSIPAddress: string;
};
export type Query = {
__typename?: 'Query';
post?: Maybe<Post>;
};
export type QueryPostArgs = {
id: Scalars['ID'];
};
export type Mutation = {
__typename?: 'Mutation';
createPost: Post;
};
export type MutationCreatePostArgs = {
post: PostInput;
};
export type Post = {
__typename?: 'Post';
id: Scalars['ID'];
title: Scalars['String'];
content: Scalars['String'];
publishedAt?: Maybe<Scalars['AWSDateTime']>;
};
export type PostInput = {
title: Scalars['String'];
content: Scalars['String'];
};
  • Scalars
  • Query and Mutation
  • Post
  • QueryPostArgs and MutationCreatePostArgs

Use the generated types

  • event: contains information about the input query (arguments, identity, etc)
  • context: contains information about the executed Lambda function
  • callback: a function you can call when your handler finishes (if you are not using async/promises)
import db from './db';
import { AppSyncResolverHandler } from 'aws-lambda';
import {Post, QueryPostArgs} from './appsync';
export const handler: AppSyncResolverHandler<QueryPostArgs, Post> = async (event) => {
const post = await db.getPost(event.arguments.id);
if (post) {
return post;
}
throw new Error('Not Found');
};
  • event.arguments will be of type QueryPostArgs (with the benefits of auto-complete!)
  • the return value, or the second argument of the callback, is expected to be of the same shape as Post (with an id, title, etc); or TypeScript will show you an error.

Advanced usage

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Benoît Bouré

Benoît Bouré

Twitter @Benoit_Boure — Need help? Hire me for a one-on-one session http://hiretheauthor.com/bboure