Concorde documentation (crawl) · interactive version

Concorde reference — DataProviderKey. The DataProviderKey<T> utility provides type-safe navigation through composite data structures. Each property or index access extends the path, and the final key can be retrieved via toString() or the Doc ID: docs/_misc/dataProviderKey. Keywords: Concorde, supersoniks, docs/_misc/dataProviderKey, dataProviderKey, DataProviderKey, reference, toString(), path, myKey.items[0], items, Item[], .path. URL: https://concorde.supersoniks.org/crawl/docs/_misc/dataProviderKey.html.

DataProviderKey

The DataProviderKey<T> utility provides type-safe navigation through composite data structures. Each property or index access extends the path, and the final key can be retrieved via toString() or the path property.

For a single HTTP path string (no dot-syntax), see Endpoint. For DataProviderKey<APIConfiguration>, see API configuration.

Principle

DataProviderKey uses a Proxy to intercept property access and build a cumulative path string. TypeScript infers the nested type at each level, so myKey.items[0] is correctly typed as DataProviderKey<Item> when items is Item[].

In Lit demos, bind HTML attributes from a key’s .path (single source of truth), and use get / set / dp instead of PublisherManager.get("…"):

import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
import { get, set } from "@supersoniks/concorde/utils";

export const myFormKey = new DataProviderKey&lt;{ email: string }&gt;("myForm");
set(myFormKey, { email: "a@b.c" });

// template: formDataProvider=${myFormKey.path}

Usage

Import

import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";

Basic example

type Item = { id: string; name: string };
//
type Data = {
  items: Item[];
  count: number;
};
//
const myKey = new DataProviderKey&lt;Data&gt;("data").items[0];
// Equivalent to: new DataProviderKey&lt;Item&gt;("data.items.0")
myKey.toString();  // "data.items.0"
myKey.path;        // same value
// myKey is typed as DataProviderKey&lt;Item&gt;

Object property access

const key = new DataProviderKey&lt;Data&gt;("data");
const countKey = key.count;
countKey.path;        // "data.count"
countKey.toString();  // "data.count"

Array index access

const itemsKey = new DataProviderKey&lt;Data&gt;("data").items;
itemsKey.path;  // "data.items"
// itemsKey is DataProviderKey&lt;Item[]&gt;
//
const firstItem = itemsKey[0];
firstItem.path;  // "data.items.0"
// firstItem is DataProviderKey&lt;Item&gt;

Dynamic paths

Use placeholders ${prop} or {$prop} in the path string. The path is resolved at runtime from the component's properties. See Dynamic path placeholders for resolution rules and skipEmptyPlaceholder. The type remains declarative:

type User = { name: string; email: string };
//
// Path resolved from component.userIndex at runtime
@subscribe(new DataProviderKey&lt;User&gt;("users.${userIndex}"))
@state()
user: User | null = null;

Dynamic keys are not supported by get, set, or dp — those APIs take a snapshot at call time with no component context. For dynamic paths use decorators (@subscribe, @publish, @handle) or sub(key) in Lit templates (resolves ${…} from the host component). See sub().

get / set / dp with static keys

For programmatic access, pass a DataProviderKey or a static path string. Dynamic placeholders are rejected:

import { dp, get, set } from "@supersoniks/concorde/utils";
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
//
const counterKey = new DataProviderKey&lt;{ count: number }&gt;("myCounter");
//
set(counterKey, { count: 0 });
dp(counterKey.count).set(1);
get(counterKey);  // snapshot: { count: 1 }

Path retrieval

The final path is built by concatenating each accessed property with a dot:

Use toString() or path to get the full path string:

const key = new DataProviderKey&lt;Data&gt;("data").count;
const pathString = key.toString();  // "data.count"
const pathProp = key.path;           // "data.count"

Use cases

Integration with @subscribe, @publish and @handle

Use DataProviderKey with @subscribe (read-only), @publish (write-only), or @handle (method callback on assign). With @subscribe / @publish, the decorated property must match the key’s value type. With @handle, the method receives (value: T).

import { subscribe } from "@supersoniks/concorde/decorators";
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
//
type FormData = { email: string };
const formKey = new DataProviderKey&lt;FormData&gt;("formData");
//
@customElement("user-form")
export class UserForm extends LitElement {
  @subscribe(formKey.email)
  @state()
  email = "";
//
  render() {
    return html`&lt;input .value=${this.email} @input=${(e) => this.email = (e.target as HTMLInputElement).value}&gt;`;
  }
}

These decorators support dynamic paths: "base.${prop}" in the constructor. A wrong property type (e.g. number for DataProviderKey<string>) is a TypeScript error. Resolution rules: Dynamic path placeholders. See @handle for method callbacks.

Notes