Skip to content

TypeScript 5.9 Compatibility Issue: Uint8Array Type Incompatibility with Schema.Uint8Array #5326

@schickling

Description

@schickling

Summary

TypeScript 5.9 introduces breaking changes to TypedArray generics that cause type compatibility issues with Effect's Schema.Uint8Array and potentially other APIs that expose Uint8Array types.

Problem Description

When using TypeScript 5.9, the following type error occurs:

Type 'Uint8Array<ArrayBufferLike>' is not assignable to type 'Uint8Array<ArrayBuffer>'
  Type 'ArrayBufferLike' is not assignable to type 'ArrayBuffer'
    Type 'SharedArrayBuffer' is not assignable to type 'ArrayBuffer'

This affects:

  • Schema.Uint8Array decoding/encoding operations
  • APIs that expect Uint8Array<ArrayBuffer> but receive Uint8Array<ArrayBufferLike>
  • Potentially other Effect APIs that expose Uint8Array types (e.g., Transferable)

Root Cause

TypeScript 5.9 introduced significant changes to TypedArray handling:

  1. TypedArrays are now generic over ArrayBufferLike: All TypedArray types (including Uint8Array) now have a generic type parameter for the underlying buffer type, defaulting to ArrayBufferLike.

  2. ArrayBufferLike now includes SharedArrayBuffer: The union type ArrayBufferLike now includes both ArrayBuffer and SharedArrayBuffer, which have diverging interfaces in ES2024.

  3. Breaking assignment compatibility: SharedArrayBuffer is no longer assignment-compatible with ArrayBuffer due to different capabilities (resizing, growing, etc.).

Reproduction

import { Schema } from "effect"

const uint8ArraySchema = Schema.Uint8Array

// This now fails in TypeScript 5.9
const decoded = Schema.decodeUnknownSync(uint8ArraySchema)(new Uint8Array([1, 2, 3]))
// Type 'Uint8Array<ArrayBufferLike>' is not assignable to type 'Uint8Array<ArrayBuffer>'

// Functions expecting specific Uint8Array<ArrayBuffer> also fail
function processBuffer(data: Uint8Array<ArrayBuffer>) {
  // Process buffer
}

processBuffer(decoded) // Type error in TS 5.9

Current Workaround

Currently, the workaround is to cast to the expected type:

const decoded = Schema.decodeUnknownSync(uint8ArraySchema)(new Uint8Array([1, 2, 3])) as Uint8Array<ArrayBuffer>

Proposed Solution

Effect should update its type definitions to handle the new TypeScript 5.9 TypedArray generics properly. This might involve:

  1. Updating Schema.Uint8Array: Ensure it properly handles both ArrayBuffer and SharedArrayBuffer cases or explicitly constrains to ArrayBuffer when appropriate.

  2. Review related APIs: Check other Effect APIs that expose Uint8Array types for similar compatibility issues.

  3. Consider type parameter constraints: Use explicit type parameters like Uint8Array<ArrayBuffer> in API signatures where SharedArrayBuffer is not intended.

References

Impact

This issue affects any Effect codebase that:

  • Uses Schema.Uint8Array for binary data processing
  • Upgrades to TypeScript 5.9
  • Has strict type checking enabled

The issue prevents clean TypeScript compilation without type assertions, potentially masking real type safety issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions