TypeScript adds type safety to Lottie integrations — typed animation data, typed refs, typed event callbacks, and typed programmatic APIs. This guide covers every TypeScript-specific pattern for lottie-web and the React/Vue wrappers.
Before You Start
Open your Lottie files in IconKing first:
- Verify colors, timing, and layer structure
- Convert
.json→.lottiefor 75% smaller files - Catch rendering issues before wiring up TypeScript
Setup: lottie-web with TypeScript
npm install lottie-web
npm install --save-dev @types/lottie-web
The @types/lottie-web package provides full typings for the lottie-web API.
Basic Typed Usage
import lottie, { AnimationItem, AnimationConfig } from 'lottie-web';
const config: AnimationConfig = {
container: document.getElementById('container') as HTMLElement,
renderer: 'svg',
loop: true,
autoplay: true,
path: '/animations/loading.json',
};
const anim: AnimationItem = lottie.loadAnimation(config);
The AnimationItem type gives you full autocomplete on methods:
anim.play();
anim.pause();
anim.stop();
anim.destroy();
anim.setSpeed(1.5);
anim.setDirection(1); // 1 = forward, -1 = reverse
anim.goToAndPlay(0, true); // frame 0, isFrame = true
anim.goToAndStop(30, true);
Typed Animation Data
When bundling animation JSON directly (not via path), type the import:
import type { AnimationData } from 'lottie-web';
import animJson from './animations/loading.json';
// Cast the imported JSON to AnimationData
const animData = animJson as unknown as AnimationData;
const anim = lottie.loadAnimation({
container: el,
renderer: 'svg',
loop: true,
autoplay: true,
animationData: animData,
});
The as unknown as AnimationData cast is necessary because TypeScript infers imported JSON as a literal type, not the broader AnimationData shape.
Typed Event Listeners
import lottie, { AnimationItem, AnimationEventName } from 'lottie-web';
const anim: AnimationItem = lottie.loadAnimation({ /* ... */ });
// Typed event names
anim.addEventListener('complete', () => {
console.log('Animation finished');
});
anim.addEventListener('loopComplete', () => {
console.log('Loop completed');
});
anim.addEventListener('enterFrame', (e) => {
// e.currentTime is the current frame number
console.log('Frame:', e.currentTime);
});
anim.addEventListener('segmentStart', (e) => {
console.log('Segment started:', e.firstFrame, e.totalFrames);
});
anim.addEventListener('DOMLoaded', () => {
console.log('DOM ready, can use addValueCallback');
});
Available typed event names:
-
'complete'— non-looping animation finished -
'loopComplete'— one loop cycle finished -
'enterFrame'— fires on each frame -
'segmentStart'— new segment started -
'DOMLoaded'— animation SVG/canvas rendered -
'destroy'— animation instance destroyed -
'data_ready'— animation data loaded -
'data_failed'— animation data failed to load
Typed addValueCallback
import lottie, { AnimationItem } from 'lottie-web';
type LottieColor = [number, number, number, number]; // [R, G, B, A] 0–1
const anim: AnimationItem = lottie.loadAnimation({ /* ... */ });
function hexToLottieColor(hex: string): LottieColor {
const r = parseInt(hex.slice(1, 3), 16) / 255;
const g = parseInt(hex.slice(3, 5), 16) / 255;
const b = parseInt(hex.slice(5, 7), 16) / 255;
return [r, g, b, 1];
}
anim.addEventListener('DOMLoaded', () => {
anim.addValueCallback(
['**', 'Fill 1', 'Color'],
(): LottieColor => hexToLottieColor('#3366FF')
);
});
React + TypeScript
With lottie-react
npm install lottie-react
lottie-react ships with its own TypeScript types:
import Lottie, { LottieRefCurrentProps } from 'lottie-react';
import { useRef } from 'react';
import animData from './animations/success.json';
export default function SuccessAnimation() {
const lottieRef = useRef<LottieRefCurrentProps>(null);
function handlePlay() {
lottieRef.current?.play();
}
function handleStop() {
lottieRef.current?.stop();
}
return (
<>
<div style={{ width: 200, height: 200 }}>
<Lottie
lottieRef={lottieRef}
animationData={animData}
loop={false}
autoplay={false}
onComplete={() => console.log('done')}
/>
</div>
<button onClick={handlePlay}>Play</button>
<button onClick={handleStop}>Stop</button>
</>
);
}
Typed Props Interface
interface AnimatedIconProps {
animationData: object;
size?: number;
loop?: boolean;
autoplay?: boolean;
onComplete?: () => void;
className?: string;
}
export function AnimatedIcon({
animationData,
size = 48,
loop = false,
autoplay = true,
onComplete,
className,
}: AnimatedIconProps) {
return (
<div style={{ width: size, height: size }} className={className}>
<Lottie
animationData={animationData}
loop={loop}
autoplay={autoplay}
onComplete={onComplete}
/>
</div>
);
}
Custom Hook with Types
import { useRef, useEffect, RefObject } from 'react';
import lottie, { AnimationItem } from 'lottie-web';
interface UseLottieOptions {
path: string;
loop?: boolean;
autoplay?: boolean;
}
interface UseLottieReturn {
containerRef: RefObject<HTMLDivElement>;
play: () => void;
pause: () => void;
stop: () => void;
setSpeed: (speed: number) => void;
}
export function useLottie({
path,
loop = true,
autoplay = true,
}: UseLottieOptions): UseLottieReturn {
const containerRef = useRef<HTMLDivElement>(null);
const animRef = useRef<AnimationItem | null>(null);
useEffect(() => {
if (!containerRef.current) return;
animRef.current = lottie.loadAnimation({
container: containerRef.current,
renderer: 'svg',
loop,
autoplay,
path,
});
return () => {
animRef.current?.destroy();
animRef.current = null;
};
}, [path, loop, autoplay]);
return {
containerRef,
play: () => animRef.current?.play(),
pause: () => animRef.current?.pause(),
stop: () => animRef.current?.stop(),
setSpeed: (speed) => animRef.current?.setSpeed(speed),
};
}
// Usage
function MyComponent() {
const { containerRef, play, pause } = useLottie({
path: '/animations/icon.json',
loop: true,
autoplay: true,
});
return (
<div>
<div ref={containerRef} style={{ width: 100, height: 100 }} />
<button onClick={play}>Play</button>
<button onClick={pause}>Pause</button>
</div>
);
}
Vue 3 + TypeScript
npm install vue3-lottie
<script setup lang="ts">
import { ref } from 'vue'
import Vue3Lottie, { LottieAnimation } from 'vue3-lottie'
import animData from './animations/loading.json'
const lottieRef = ref<InstanceType<typeof LottieAnimation> | null>(null)
function play() {
lottieRef.value?.play()
}
function pause() {
lottieRef.value?.pause()
}
</script>
<template>
<Vue3Lottie
ref="lottieRef"
:animation-data="animData"
:loop="true"
:auto-play="true"
:width="200"
:height="200"
/>
<button @click="play">Play</button>
<button @click="pause">Pause</button>
</template>
dotLottie + TypeScript
@lottiefiles/dotlottie-web ships with TypeScript types:
npm install @lottiefiles/dotlottie-web
import { DotLottie, DotLottieConfig } from '@lottiefiles/dotlottie-web';
const config: DotLottieConfig = {
canvas: document.getElementById('canvas') as HTMLCanvasElement,
src: '/animations/loading.lottie',
loop: true,
autoplay: true,
};
const dotLottie: DotLottie = new DotLottie(config);
// Typed event listeners
dotLottie.addEventListener('play', () => console.log('playing'));
dotLottie.addEventListener('complete', () => console.log('done'));
dotLottie.addEventListener('frame', (e) => {
console.log('Frame:', e.currentFrame);
});
// Cleanup
dotLottie.destroy();
React + dotLottie TypeScript
npm install @lottiefiles/dotlottie-react
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
import type { DotLottieReactProps } from '@lottiefiles/dotlottie-react';
interface AnimatedLoaderProps extends Partial<DotLottieReactProps> {
size?: number;
}
export function AnimatedLoader({ size = 100, ...props }: AnimatedLoaderProps) {
return (
<DotLottieReact
src="/animations/loading.lottie"
loop
autoplay
style={{ width: size, height: size }}
{...props}
/>
);
}
Typing Animation Segments
type AnimationSegment = [number, number]; // [startFrame, endFrame]
const segments: Record<string, AnimationSegment> = {
idle: [0, 30],
active: [31, 60],
success: [61, 90],
};
function playSegment(anim: AnimationItem, name: keyof typeof segments) {
anim.playSegments(segments[name], true);
}
// Usage
playSegment(anim, 'success');
tsconfig Notes
If you're importing .json directly, enable these in tsconfig.json:
{
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true
}
}
Summary
- Install
@types/lottie-webfor full lottie-web typings - Use
AnimationItemtype for animation instances - Type refs as
useRef<LottieRefCurrentProps>(null)with lottie-react - Define
LottieColoras[number, number, number, number]foraddValueCallback -
@lottiefiles/dotlottie-weband@lottiefiles/dotlottie-reactinclude types out of the box - Use
keyof typeofpatterns for typed segment names
Before integrating: preview and convert files at IconKing — no account needed.
Top comments (0)