Extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more.
—
Uppy provides comprehensive TypeScript definitions for all components, options, and events. The package includes full type safety with generic support for custom metadata and response body types.
Uppy uses generic type parameters to provide type safety for custom metadata and response bodies.
/**
* Core generic type parameters used throughout Uppy
*/
interface Meta {
[key: string]: any;
}
interface Body {
[key: string]: any;
}
// Usage with custom types
interface MyMetadata {
userId: string;
projectId: string;
tags: string[];
caption?: string;
}
interface MyResponseBody {
fileId: string;
url: string;
thumbnailUrl?: string;
}
const uppy = new Uppy<MyMetadata, MyResponseBody>({
meta: {
userId: 'user123',
projectId: 'proj456',
tags: ['work', 'important']
}
});Complete type definitions for file objects and related interfaces.
/**
* Core file object with full type safety
*/
interface UppyFile<M extends Meta = {}, B extends Body = {}> {
id: string;
name: string;
extension: string;
meta: M & UppyFileMeta;
type?: string;
data: Blob | File;
progress?: FileProgress;
size: number;
isGhost: boolean;
source?: string;
remote?: Remote;
preview?: string;
}
interface UppyFileMeta {
name: string;
type?: string;
relativePath?: string;
[key: string]: any;
}
interface FileProgress {
percentage: number;
bytesUploaded: number;
bytesTotal: number;
uploadComplete: boolean;
uploadStarted: number | null;
}
interface Remote {
companionUrl: string;
url: string;
body?: { [key: string]: any };
headers?: { [key: string]: string };
}Complete type definitions for Uppy's internal state management.
/**
* Core Uppy state interface
*/
interface State<M extends Meta = {}, B extends Body = {}> {
files: { [fileId: string]: UppyFile<M, B> };
currentUploads: { [uploadId: string]: CurrentUpload<M, B> };
allowNewUpload: boolean;
capabilities: Capabilities;
totalProgress: number;
meta: M;
info: InfoObject | null;
plugins: { [pluginId: string]: BasePlugin<any, any, any> };
}
interface CurrentUpload<M extends Meta = {}, B extends Body = {}> {
fileIDs: string[];
step: number;
result?: UploadResult<M, B>;
}
interface Capabilities {
individualCancellation?: boolean;
uploadProgress?: boolean;
editMetadata?: boolean;
resumableUploads?: boolean;
}
interface InfoObject {
message: string;
type: 'info' | 'warning' | 'error' | 'success';
details?: string;
}Comprehensive event system with full type safety.
/**
* Complete event map with typed handlers
*/
interface UppyEventMap<M extends Meta = {}, B extends Body = {}> {
// File management events
'file-added': (file: UppyFile<M, B>) => void;
'file-removed': (file: UppyFile<M, B>, reason?: string) => void;
'files-added': (files: UppyFile<M, B>[]) => void;
// Upload lifecycle events
'upload': (data: { id: string; fileIDs: string[] }) => void;
'upload-start': (data: { id: string; fileIDs: string[] }) => void;
'upload-progress': (file: UppyFile<M, B>, progress: FileProgress) => void;
'upload-success': (file: UppyFile<M, B>, response: UploadSuccessResponse<B>) => void;
'upload-error': (file: UppyFile<M, B>, error: Error, response?: UploadErrorResponse<M, B>) => void;
'upload-retry': (fileId: string) => void;
'complete': (result: UploadResult<M, B>) => void;
// State management events
'state-update': (prev: State<M, B>, next: State<M, B>, patch: Partial<State<M, B>>) => void;
'info-visible': () => void;
'info-hidden': () => void;
// Restriction and validation events
'restriction-failed': (file: UppyFile<M, B>, error: Error) => void;
'file-editor:cancel': (file?: UppyFile<M, B>) => void;
'file-editor:complete': (file?: UppyFile<M, B>) => void;
// Cancel events
'cancel-all': () => void;
}
interface UploadResult<M extends Meta = {}, B extends Body = {}> {
successful: UppyFile<M, B>[];
failed: UppyFile<M, B>[];
uploadID: string;
}
interface UploadSuccessResponse<B extends Body = {}> {
status: number;
body: B;
uploadURL?: string;
}
interface UploadErrorResponse<M extends Meta = {}, B extends Body = {}> {
status: number;
body: any;
message?: string;
details?: string;
}Type definitions for plugin development and configuration.
/**
* Plugin option types for all official plugins
*/
export type {
// Core types
UppyOptions, UIPluginOptions,
// UI Plugin options
DashboardOptions, DragDropOptions, FileInputOptions, DropTargetOptions,
ProgressBarOptions, StatusBarOptions, InformerOptions,
// File source options
WebcamOptions, AudioOptions, ScreenCaptureOptions,
ImageEditorOptions, CompressorOptions,
// Cloud provider options
GoogleDriveOptions, DropboxOptions, BoxOptions, OneDriveOptions,
InstagramOptions, FacebookOptions, UnsplashOptions, UrlOptions,
RemoteSourcesOptions, ZoomOptions,
// Upload handler options
TusOptions, XHRUploadOptions, AwsS3Options, TransloaditOptions,
// Utility plugin options
ThumbnailGeneratorOptions, GoldenRetrieverOptions, FormOptions
};
/**
* Plugin base class type definitions
*/
abstract class BasePlugin<Options = {}, State = {}, Events = {}> {
readonly id: string;
readonly type: string;
readonly uppy: Uppy<any, any>;
readonly opts: Options;
constructor(uppy: Uppy<any, any>, options?: Options);
abstract install(): void;
abstract uninstall(): void;
protected setOptions(newOptions: Partial<Options>): void;
protected getPluginState(): State;
protected setPluginState(patch: Partial<State>): void;
}
abstract class UIPlugin<Options = {}, State = {}> extends BasePlugin<Options, State> {
protected render(): ComponentChild;
protected mount(target: string | Element, plugin: UIPlugin<any, any>): void;
protected unmount(): void;
protected rerender(): void;
protected getElement(): Element | null;
}Complete type definitions for Uppy configuration options.
/**
* Core Uppy configuration options
*/
interface UppyOptions<M extends Meta = {}, B extends Body = {}> {
id?: string;
autoProceed?: boolean;
allowMultipleUploads?: boolean;
debug?: boolean;
restrictions?: Restrictions;
meta?: M;
onBeforeFileAdded?: (
currentFile: UppyFile<M, B>,
files: { [fileId: string]: UppyFile<M, B> }
) => UppyFile<M, B> | boolean | undefined;
onBeforeUpload?: (
files: { [fileId: string]: UppyFile<M, B> }
) => { [fileId: string]: UppyFile<M, B> } | boolean | undefined;
locale?: Locale;
store?: Store;
logger?: Logger;
infoTimeout?: number;
}
interface Restrictions {
maxFileSize?: number | null;
minFileSize?: number | null;
maxTotalFileSize?: number | null;
maxNumberOfFiles?: number | null;
minNumberOfFiles?: number | null;
allowedFileTypes?: string[] | null;
requiredMetaFields?: string[];
}
interface Locale {
strings: LocaleStrings;
pluralize?: (count: number) => number;
}
interface LocaleStrings {
[key: string]: string | LocaleStrings;
}
interface Store {
getState(): any;
setState(patch: any): void;
subscribe(listener: () => void): () => void;
}
interface Logger {
debug(...args: any[]): void;
warn(...args: any[]): void;
error(...args: any[]): void;
}Helper types for common TypeScript patterns in Uppy usage.
/**
* Utility types for common patterns
*/
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
type PluginOptions<T> = T extends BasePlugin<infer Options, any, any> ? Options : never;
type FileWithMeta<M extends Meta> = UppyFile<M, any>;
type UploadHandler<M extends Meta, B extends Body> = (
files: UppyFile<M, B>[],
options: any
) => Promise<UploadResult<M, B>>;
/**
* Plugin constructor type helper
*/
type PluginConstructor<Options = {}, State = {}> = {
new (uppy: Uppy<any, any>, options?: Options): BasePlugin<Options, State>;
};
/**
* Event handler type helper
*/
type EventHandler<T extends keyof UppyEventMap<any, any>> = UppyEventMap<any, any>[T];Examples demonstrating advanced TypeScript usage patterns.
/**
* Advanced TypeScript usage examples
*/
// Custom metadata interface
interface ProjectMetadata {
projectId: string;
userId: string;
department: 'engineering' | 'design' | 'marketing';
tags: string[];
priority: 'low' | 'medium' | 'high';
dueDate?: Date;
}
// Custom response body interface
interface UploadResponseBody {
fileId: string;
publicUrl: string;
thumbnailUrl?: string;
processingStatus: 'pending' | 'complete' | 'failed';
metadata: {
width?: number;
height?: number;
duration?: number;
};
}
// Type-safe Uppy instance
const typedUppy = new Uppy<ProjectMetadata, UploadResponseBody>({
debug: true,
restrictions: {
maxFileSize: 10 * 1024 * 1024,
allowedFileTypes: ['image/*', 'video/*']
},
meta: {
projectId: 'proj-123',
userId: 'user-456',
department: 'engineering',
tags: ['prototype', 'testing'],
priority: 'high'
},
onBeforeFileAdded: (currentFile, files) => {
// Type-safe file metadata access
console.log('Adding file for project:', currentFile.meta.projectId);
console.log('User department:', currentFile.meta.department);
// Validation with full type safety
if (currentFile.meta.priority === 'high' && Object.keys(files).length >= 5) {
return false; // Reject file
}
return currentFile;
}
});
// Type-safe event handlers
typedUppy.on('upload-success', (file, response) => {
// Full type safety for custom metadata and response
console.log(`File ${file.name} uploaded for project ${file.meta.projectId}`);
console.log(`Available at: ${response.body.publicUrl}`);
console.log(`Processing status: ${response.body.processingStatus}`);
if (response.body.metadata.width && response.body.metadata.height) {
console.log(`Image dimensions: ${response.body.metadata.width}x${response.body.metadata.height}`);
}
});
// Type-safe plugin usage with custom options
interface CustomDashboardMeta extends ProjectMetadata {
uploadReason: string;
}
typedUppy.use(Dashboard, {
target: '#uppy-dashboard',
metaFields: [
{ id: 'uploadReason', name: 'Upload Reason', placeholder: 'Why are you uploading this file?' },
{ id: 'priority', name: 'Priority' },
{ id: 'tags', name: 'Tags' }
] as MetaField[],
onRequestCloseModal: () => {
const files = typedUppy.getFiles();
const hasHighPriority = files.some(file => file.meta.priority === 'high');
if (hasHighPriority) {
return confirm('You have high priority files. Are you sure you want to close?');
}
return true;
}
});/**
* Module declaration for CSS imports (when using bundlers)
*/
declare module "*.css" {
const content: string;
export default content;
}
/**
* Global type augmentation for window object
*/
declare global {
interface Window {
Uppy?: typeof Uppy;
}
}
/**
* Preact component types for UI plugins
*/
type ComponentChild = any;
type ComponentRender = (type: any, props?: any, ...children: ComponentChild[]) => ComponentChild;Install with Tessl CLI
npx tessl i tessl/npm-uppy