Modern Approaches for End-to-End Type Safety Using TypeScript
Startups
Enterprise
TypeScript
Using TypeScript
You should be using TypeScript

Types are documentation...
...from your present...

...to your future self.

Types
=
Tools
What is end-to-end?
Approaches to
Type-Safety
Code Generation
- A tool is used to create derivative types or code from a source
- The code is used in part of the application
- Can be used in local development or as part of the build process
Type Inference
- A type is inferred by TypeScript when an explicit type annotation is not provided
- Works for primitive values, objects, function return types, etc.
- Default parameter values
TypeScript types go out
TypeScript types come in
Derive along the way
Stack | Options |
---|---|
Infrastructure | AWS CDK SST Pulumi |
Database | Prisma EdgeDB TypeORM |
Frontend and Backend (API) | Swagger GraphQL tRPC |
End-to-End (Full-Stack)
Infrastructure
-
AWS CDK
-
SST
-
Pulumi
Infrastructure as Code
- Infrastructure as Code (IaC) is the managing and provisioning of infrastructure through code instead of through manual processes.*
- The code can be version controlled just like any other file so that changes can be tracked over time.
- Yes, it can be written in TypeScript!
Adopt
- You're already using AWS
- You're not using AWS but you want to
- You want or need infra-as-code as part of your project/organization
Avoid
- You're not using AWS and you want to keep it that way
- Smaller projects that don't need the buy-in
- Another thing to learn
AWS CDK
AWS Cloud Development Kit - Website
import * as cdk from 'aws-cdk-lib';
import {NodejsFunction} from 'aws-cdk-lib/aws-lambda-nodejs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as path from 'path';
export class CdkStarterStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const myFunction = new NodejsFunction(this, 'my-function', {
memorySize: 1024,
timeout: cdk.Duration.seconds(5),
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'main',
entry: path.join(__dirname, `/../src/my-lambda/index.ts`),
});
}
}
Adopt
- You want or need Serverless applications
- AWS only
- IaC with local development
Avoid
- Serverless doesn't fit your architecture or use-case
- You don't want to use AWS
SST
Serverless Stack - Website
import * as sst from "@serverless-stack/resources";
export default class MyStack extends sst.Stack {
constructor(scope: sst.App, id: string, props?: sst.StackProps) {
super(scope, id, props);
// Create the HTTP API
const api = new Api(stack, "Api", {
routes: {
"GET /notes": "src/list.handler",
"GET /notes/{id}": "src/get.handler",
"PUT /notes/{id}": "src/update.handler",
},
});
// Show the API endpoint in the output
stack.addOutputs({
ApiEndpoint: api.url,
});
}
}
Adopt
- You want IaC across one or more cloud providers
- Provider-agnostic
- Unit-testable IaC (example)
Avoid
- Smaller projects that don't need the buy-in
- Another thing to learn
Pulumi
Universal IaC - Website
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Create an AWS resource (S3 Bucket)
const bucket = new aws.s3.Bucket("my-bucket");
// Export the name of the bucket
export const bucketName = bucket.id;
Database
-
TypeORM
-
Prisma
-
EdgeDB
Adopt
- Familiar with traditional ORM patterns and practices
- Performance compared to Prisma
- Full-featured - all-around good choice
Avoid
- Not as declarative
- More verbose than Prisma
- Querying
- Data-model
- Only limit-offset pagination is supported
TypeORM
ORM a la Hibernate/Entity Framework - Website
Database
Adopt
- You're using a supported database
- Full database workflow coverage
- Full type-safety
Avoid
- Full database query support
- Automatic database CRUD
- Automatic API
Prisma
Prisma Client - Website
Database
Demo
Prisma Client for TypeScript
Adopt
- New and Shiny
- Throughput and latency are paramount (benchmark)
Avoid
- Need to keep existing database infra
- Existing performance is "good enough"
- IMO - client is not as ergonomic as Prisma
EdgeDB
Graph-relational database - Website
Database
Demo
EdgeDB TypeScript Client
Back-end (API) to Front-end
-
Nothing 😬
-
Swagger
-
GraphQL
-
tRPC
Adopt
- Just don't
- If you do, be ready for pain
Avoid
- Absolutely
- If at all possible
Nothing
The Wild West
In all seriousness, consider that using TypeScript in a backend will pay massive dividends in run-time safety for your applications.
Back-end
Adopt
- Other options are not an option
- Basic prototypes
- Consistent JSON
- Run-time validation is an option
Avoid
- Complex JSON
- Low sample size
- If other solutions are available
QuickType
Convert JSON into code - Website
Front-end
Demo
Adopt
- Existing (legacy) backends
- Cannot adopt GraphQL
- Smaller transition from non-swagger API
Avoid
- Types are only as good as your swagger
- Auto-gen is not always done or possible
- Versioning problems inherent to REST APIs
Swagger
OpenAPI Specification - Website
Back-end
Demo
Resources
- Express
- tRPC
Adopt
- API adheres to Swagger 2.0 or OpenAPI 3.0 spec
- Tools used in projects can leverage types
Avoid
- Types are only as good as your swagger
Swagger
OpenAPI Specification - Website
Front-end
Demo
Adopt
- Already using Redux
- React-query behavior within an established library
- Supports OpenAPI and GraphQL
Avoid
- Sworn off Redux?
- React-query is an option
- Provided structure is not needed
Redux-Toolkit
RTK-query Codegen - Website
Front-end
Demo
RTK Codegen
Adopt
- Full type-safety
- Separate teams
- Established contacts
Avoid
- Adoption/learning curve
- Slight increase in complexity
GraphQL
GraphQL Specification - Website
Back-end
Demo
Now Playing Apollo GraphQL Server
Resources
Tips
- REST APIs can be generated from GraphQL APIs, but not the other way around
- Backend for front-end pattern
Adopt
- GraphQL back-end
- Perfect type-safety
- Autocomplete all the things
Avoid
- Code generation is impractical
- Backend is not using GraphQL
GraphQL
Multiple Options - Website
Front-end
Demo
Now Playing GraphQL React App
Adopt
- Able to use a mono-repo
- Type-safety without code generation
- Backend is TS
Avoid
- You need to use types outside the project
- You need types in other languages
- Your projects are in different repositories
tRPC
End-to-end typesafe APIs - Website
Back-end
Demo
trpc-server -> tmdb-router
Adopt
- tRPC back-end
- Perfect type-safety
- Autocomplete all the things
- No code generation!
Avoid
- Backend is not tRPC
- Except if you use trpc-openapi...
- Backend is not part of the same repository
tRPC
TypeScript RPC - Website
Front-end
Demo
trpc-client
Honorable Mentions
-
Wundergraph
-
Pothos (coming soon...)
-
GQty
Building React Apps with TypeScript


Securing a GraphQL API with Apollo 3


Thank you!

@mwarger
Slides + Code

Modern Approaches for End-to-End Type Safety Using TypeScript [KCDC 2022]
By Mat Warger
Modern Approaches for End-to-End Type Safety Using TypeScript [KCDC 2022]
When developing front-end applications with TypeScript, a common pain point is synchronizing your API data types with your UI. In this session, we'll look at a number of tools and techniques for taming this complexity. Whether you need a REST API or a GraphQL API, you'll learn how to leverage a combination of types and code generation to modernize your development experience from the server to the client.
- 1,303