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<{ email: string }>("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<Data>("data").items[0];
// Equivalent to: new DataProviderKey<Item>("data.items.0")
myKey.toString(); // "data.items.0"
myKey.path; // same value
// myKey is typed as DataProviderKey<Item>
Object property access
const key = new DataProviderKey<Data>("data");
const countKey = key.count;
countKey.path; // "data.count"
countKey.toString(); // "data.count"
Array index access
const itemsKey = new DataProviderKey<Data>("data").items;
itemsKey.path; // "data.items"
// itemsKey is DataProviderKey<Item[]>
//
const firstItem = itemsKey[0];
firstItem.path; // "data.items.0"
// firstItem is DataProviderKey<Item>
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<User>("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<{ count: number }>("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:
new DataProviderKey<T>("base")→"base"key.prop→"base.prop"key.items[0]→"base.items.0"
Use toString() or path to get the full path string:
const key = new DataProviderKey<Data>("data").count;
const pathString = key.toString(); // "data.count"
const pathProp = key.path; // "data.count"
Use cases
- Type-safe bindings: paths for
@bind,@subscribe,@publish,@handle - Dynamic paths: reusable keys with
${...}placeholders - Form fields: form data paths with compile-time checking
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<FormData>("formData");
//
@customElement("user-form")
export class UserForm extends LitElement {
@subscribe(formKey.email)
@state()
email = "";
//
render() {
return html`<input .value=${this.email} @input=${(e) => this.email = (e.target as HTMLInputElement).value}>`;
}
}
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
- Function properties are excluded from navigation (no
key.method()chaining) - Primitives have no navigable properties
- The
pathproperty andtoString()are equivalent for retrieving the key