LLM Skills
~/catalog/debugging & maintenance//SKILL

Expo system class api migration

/SKILL

Fix for expo-file-system migration errors when upgrading to Expo SDK 52+. Use when:

// skill content

--- name: expo-file-system-class-api-migration description: | Fix for expo-file-system migration errors when upgrading to Expo SDK 52+. Use when: (1) TypeScript error "Property 'cacheDirectory' does not exist on type", (2) "Module has no exported member 'EncodingType'" error, (3) "Property 'deleteAsync' does not exist" or similar FileSystem function errors, (4) file.info returns a function instead of file info object, (5) Upgrading Expo SDK and expo-file-system code breaks. Covers migration from legacy function-based API (FileSystem.deleteAsync, getInfoAsync) to new class-based API (File, Directory, Paths classes). author: Claude Code version: 1.0.0 date: 2025-01-23 --- # Expo File System Class API Migration ## Problem After upgrading to Expo SDK 52+ (expo-file-system 18+), the legacy function-based API no longer works. Code using FileSystem.deleteAsync(), FileSystem.getInfoAsync(), FileSystem.cacheDirectory, etc. will fail with TypeScript errors or runtime issues. ## Context / Trigger Conditions You'll encounter this when: - Upgrading Expo SDK from 51 or earlier to 52+ - TypeScript errors like: - Property 'cacheDirectory' does not exist on type 'typeof import("expo-file-system")' - Module '"expo-file-system"' has no exported member 'EncodingType' - Property 'deleteAsync' does not exist - Property 'getInfoAsync' does not exist - Runtime issues where file.info returns a function instead of file metadata - Any code importing import * as FileSystem from 'expo-file-system' ## Solution ### 1. Change Import Style ``typescript // OLD (legacy API) import * as FileSystem from 'expo-file-system'; // NEW (class-based API) import { File, Directory, Paths } from 'expo-file-system'; ` ### 2. Replace Common Operations | Legacy API | New Class-Based API | |------------|---------------------| | FileSystem.cacheDirectory | Paths.cache | | FileSystem.documentDirectory | Paths.document | | FileSystem.deleteAsync(uri, { idempotent: true }) | new File(uri).delete() | | FileSystem.getInfoAsync(uri) | new File(uri).exists (for existence check) | | FileSystem.writeAsStringAsync(uri, content, { encoding: 'base64' }) | new File(path, name).write(content, { encoding: 'base64' }) | | FileSystem.readAsStringAsync(uri) | new File(uri).text() | ### 3. File Creation Pattern `typescript // OLD const filePath = ${FileSystem.cacheDirectory}voice_${Date.now()}.mp3; await FileSystem.writeAsStringAsync(filePath, base64Data, { encoding: FileSystem.EncodingType.Base64 }); // NEW const fileName = voice_${Date.now()}.mp3; const file = new File(Paths.cache, fileName); await file.write(base64Data, { encoding: 'base64' }); const uri = file.uri; ` ### 4. File Deletion Pattern `typescript // OLD await FileSystem.deleteAsync(uri, { idempotent: true }); // NEW try { const file = new File(uri); if (file.exists) { await file.delete(); } } catch { // Ignore delete errors (equivalent to idempotent) } ` ### 5. File Info Pattern `typescript // OLD const info = await FileSystem.getInfoAsync(uri); if (info.exists && info.modificationTime) { // use info.modificationTime } // NEW - Note: info is now a METHOD, not a property const file = new File(uri); if (file.exists) { // For modification time, use filename timestamps or other approach // The new API structure differs for file metadata } ` ### 6. Directory Listing `typescript // OLD const files = await FileSystem.readDirectoryAsync(cacheDir); // NEW const cacheDir = Paths.cache; const contents = cacheDir.list(); // Returns array of File/Directory objects for (const item of contents) { if (item instanceof File) { console.log(item.name, item.uri); } } ` ## Verification After migration: 1. Run npx tsc --noEmit - should pass with no expo-file-system errors 2. Test file operations in the app to ensure they work correctly ## Example Complete before/after for a voice message cache cleanup: `typescript // BEFORE (Legacy API) import * as FileSystem from 'expo-file-system'; export async function cleanupAudioCache(maxAgeMs: number): Promise<void> { const cacheDir = FileSystem.cacheDirectory; if (!cacheDir) return; const files = await FileSystem.readDirectoryAsync(cacheDir); const now = Date.now(); for (const fileName of files) { if (fileName.startsWith('voice_') && fileName.endsWith('.mp3')) { const filePath = ${cacheDir}${fileName}`; const info = await FileSystem.getInfoAsync(filePath); if (info.exists && info.modificationTime) { const age = now - info.modificationTime * 1000; if (age > maxAgeMs) { await FileSystem.deleteAsync(filePath, { idempotent: true }); } } } } } // AFTER (Class-Based API) import { File, Paths } from 'expo-file-system'; export async function cleanupAudioCache(maxAgeMs: number): Promise<void> { const cacheDir = Paths.cache; const contents = cacheDir.list(); const now =

// original public source
strataga/claude-setup
/skills/expo-file-system-class-api-migration/SKILL.md
License: License not specified. Review the repository before reusing it.
Independent project, not affiliated with Anthropic. This skill remains the property of its original author.
// install this skill
Paste this command in your terminal at the root of your project:
mkdir -p .claude/commands && curl -o ".claude/commands/SKILL.md" "https://raw.githubusercontent.com/strataga/claude-setup/master/skills/expo-file-system-class-api-migration/SKILL.md"
Then in Claude Code, type /SKILL to activate it.
open_in_newOpen original source
// save
Save available after sign in.
loginSign in to save
// information
Creatorstrataga
Format.md
AccessFree
// similar

Skills Debugging & maintenance

View allarrow_forward