Skip to content

Improve SDK type safety by using CoreSchema instead of unknown #26558

@alvarosabu

Description

@alvarosabu

Describe the Bug

Context

While removing as any assertions in app/src/composables/use-collab.ts, we discovered that the SDK client isn't receiving

the schema generic it needs for proper type inference.

How SDK Generics Work

The Directus SDK is designed around a Schema generic that flows through the entire type system:

// The SDK client accepts a Schema generic
DirectusClient

// Which propagates to queries
readUsers<Schema, Query>()

// Which determines what fields are valid
Query<Schema, Item>.fields → QueryFields<Schema, Item>

When you provide a proper Schema, the SDK can:

  1. Know which collections exist (directus_users, directus_files, etc.)
  2. Know field types for each collection
  3. Detect relational fields by checking if a field's type exists in the Schema
  4. Allow nested object syntax for those relational fields: { avatar: ['id', 'modified_on'] }

The Problem

The app passes unknown as the Schema generic:

// app/src/sdk.ts
export type SdkClient = DirectusClient & AuthenticationClient & RestClient;

With unknown, the SDK's type inference chain breaks:

// SDK internals (simplified)
type RelationalFields<Schema, Item> = {
[Key in keyof Item]: Extract<Item[Key], ItemType> extends never ? never : Key;
}[keyof Item];

type ItemType = Schema[keyof Schema]; // With unknown → never

ItemType = unknown[keyof unknown] = unknown[never] = never

RelationalFields<unknown, User> = never (no fields match never)

Object syntax { avatar: [...] } is excluded from valid field types

This forces us to use as any:

fields: ['id', 'first_name', 'last_name', { avatar: ['id', 'modified_on'] }] as any

Possible solution

The SDK exports CoreSchema - a pre-defined generic that describes all system collections:

User extends the CoreSchema with the expected data structure hierarchy.

To Reproduce

  • Open IDE
  • Query the SDK with a nested field
  • Run vue-tsc

Directus Version

v15.0.0

Hosting Strategy

Self-Hosted (Docker Image)

Database

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions