How OpenCut Handles TypeScript Strict Mode and Type Safety: A Complete Technical Guide

OpenCut enforces TypeScript strict mode through a comprehensive tsconfig.json configuration and propagates type safety across UI components, routing, and form validation by combining strict compiler flags with explicit type definitions and utility generics.

OpenCut is an open-source video editing application that prioritizes type safety at every architectural layer. By enabling the full suite of strict compiler checks in apps/web/tsconfig.json and leveraging typed primitives from libraries like class-variance-authority and @tanstack/react-router, the codebase eliminates implicit any types and catches type mismatches during compilation rather than at runtime.

Strict Compiler Configuration

OpenCut’s web application uses a fully strict TypeScript configuration located in apps/web/tsconfig.json. The configuration sets "strict": true, which automatically enables noImplicitAny, strictNullChecks, strictFunctionTypes, and other strictness flags.

Additionally, the configuration includes several explicit flags to prevent unsafe patterns:

  • "noUnusedLocals": true – Errors on local variables that are never read, eliminating dead code.
  • "noUnusedParameters": true – Errors on function parameters that are never used, enforcing clean function signatures.
  • "noFallthroughCasesInSwitch": true – Disallows fall-through in switch statements, preventing logic errors.
  • "noUncheckedSideEffectImports": true – Prevents importing modules that have side effects without explicit import type declarations.
  • "skipLibCheck": true – Skips type checking of declaration files to improve build speed while maintaining strict checks on project code.

These settings force developers to explicitly type every exported API and prevent accidental any leaks from untyped dependencies.

Type-Safe Component APIs

OpenCut’s UI components combine primitive prop definitions with variant-based styling using typed generics. In apps/web/src/components/ui/button.tsx, the component merges the base button primitive’s props with variant props generated by class-variance-authority.

// apps/web/src/components/ui/button.tsx
import { Button as ButtonPrimitive } from "@base-ui/react/button"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "#/lib/utils.ts"

type ButtonProps = ButtonPrimitive.Props & VariantProps<typeof buttonVariants>

function Button({ className, variant = "default", size = "default", ...props }: ButtonProps) {
  return (
    <ButtonPrimitive
      data-slot="button"
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    />
  )
}

The ButtonProps type inherits the exact prop shape from ButtonPrimitive.Props and augments it with VariantProps<typeof buttonVariants>. This ensures that any variant name passed to the component (like variant="destructive") is checked against the defined schema at compile time, preventing invalid string literals from reaching production.

Generated Route Types

The routing layer in OpenCut achieves end-to-end type safety through @tanstack/react-router and its code generation. The file apps/web/src/routeTree.gen.ts contains autogenerated interfaces that strictly define the shape of all application routes.

// apps/web/src/routeTree.gen.ts
export interface FileRoutesByFullPath {
  [fullPath: string]: RouteRecord
}
export interface FileRoutesByTo {
  [to: string]: RouteRecord
}
export interface FileRoutesById {
  [id: string]: RouteRecord
}
export interface FileRouteTypes {
  // Strict route definitions...
}

These interfaces ensure that route parameters, search params, and path definitions are type-checked throughout the application. Because FileRouteTypes provides explicit mappings, the TypeScript compiler can verify that Link components point to valid routes and that route parameters match their expected types.

Utility Function Typing

Even small utility functions like cn (class-name merger) are written with explicit type imports to prevent arbitrary value acceptance. Located in apps/web/src/lib/utils.ts, the function uses ClassValue from clsx to constrain inputs.

// apps/web/src/lib/utils.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

The ClassValue type is a union that only permits strings, numbers, booleans, or arrays thereof. If a developer attempts to pass an object or other invalid type to cn, the TypeScript compiler flags the error immediately.

End-to-End Form Validation

OpenCut extends type safety to form handling by combining Zod schemas with React Hook Form. The zodResolver from @hookform/resolvers creates a generic type that ties form data shapes directly to validation schemas.

import { z } from "zod"
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"

const schema = z.object({
  title: z.string().min(1),
  duration: z.number().positive(),
})

type FormValues = z.infer<typeof schema>

const form = useForm<FormValues>({ resolver: zodResolver(schema) })

The FormValues type is inferred from the Zod schema, ensuring that the form object’s watch, setValue, and handleSubmit methods only accept data matching the defined structure. This pattern, confirmed by the presence of zod and @hookform/resolvers in apps/web/package.json, prevents runtime validation errors by catching type mismatches during development.

Summary

  • OpenCut enables full strict mode in apps/web/tsconfig.json with "strict": true and additional flags like noUnusedLocals and noUncheckedSideEffectImports to eliminate implicit any types and unsafe imports.
  • UI components use intersection types combining primitive props with VariantProps to create strictly typed component APIs that catch invalid prop values at compile time.
  • Route definitions rely on autogenerated interfaces in routeTree.gen.ts to ensure type-safe navigation throughout the application.
  • Utility functions like cn use explicit type imports (ClassValue) to constrain inputs and prevent runtime class-name errors.
  • Form validation leverages Zod inference with React Hook Form resolvers to maintain type safety from schema definition to submission handling.

Frequently Asked Questions

What strict TypeScript flags does OpenCut use?

OpenCut enables "strict": true in apps/web/tsconfig.json, which activates noImplicitAny, strictNullChecks, and strictFunctionTypes. Additionally, the project configures noUnusedLocals, noUnusedParameters, noFallthroughCasesInSwitch, and noUncheckedSideEffectImports to enforce clean, explicit code and prevent side-effect imports without type declarations.

How does OpenCut ensure type safety in UI components?

The codebase uses intersection types that combine base primitive props (like ButtonPrimitive.Props) with VariantProps from class-variance-authority. This pattern in apps/web/src/components/ui/button.tsx ensures that variant names, sizes, and other props are strictly checked against defined schemas, preventing invalid values from being passed to components.

How are routes type-checked in OpenCut?

OpenCut uses @tanstack/react-router to generate apps/web/src/routeTree.gen.ts, which contains explicit interfaces like FileRoutesByFullPath and FileRouteTypes. These generated types provide compile-time guarantees that route paths and parameters match the expected definitions throughout the application.

What validation library does OpenCut use for form type safety?

OpenCut uses Zod combined with @hookform/resolvers. The zodResolver creates a generic link between the Zod schema and React Hook Form's useForm hook, allowing the form values type to be inferred via z.infer<typeof schema>. This ensures that form data, validation errors, and submission handlers are all strictly typed according to the schema definition.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →