Skip to content

Commit 545112b

Browse files
authored
Update TypeScript interface (#22)
* Update the interface. It changed! * update after interface changes
1 parent b93882e commit 545112b

File tree

3 files changed

+34
-40
lines changed

3 files changed

+34
-40
lines changed

context-protocol.ts

+14-20
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,30 @@
11
// From: https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md#definitions
22

33
/**
4-
* A Context object defines an optional initial value for a Context, as well as a name identifier for debugging purposes.
4+
* A context key.
5+
*
6+
* A context key can be any type of object, including strings and symbols. The
7+
* Context type brands the key type with the `__context__` property that
8+
* carries the type of the value the context references.
59
*/
6-
export type Context<T> = {
7-
name: string;
8-
initialValue?: T;
9-
};
10+
export type Context<KeyType, ValueType> = KeyType & { __context__: ValueType };
1011

1112
/**
1213
* An unknown context type
1314
*/
14-
export type UnknownContext = Context<unknown>;
15+
export type UnknownContext = Context<unknown, unknown>;
1516

1617
/**
1718
* A helper type which can extract a Context value type from a Context type
1819
*/
1920
export type ContextType<T extends UnknownContext> =
20-
T extends Context<infer Y> ? Y : never;
21+
T extends Context<infer _, infer V> ? V : never;
2122

2223
/**
2324
* A function which creates a Context value object
2425
*/
25-
export function createContext<T>(
26-
name: string,
27-
initialValue?: T,
28-
): Readonly<Context<T>> {
29-
return {
30-
name,
31-
initialValue,
32-
};
33-
}
26+
export const createContext = <ValueType>(key: unknown) =>
27+
key as Context<typeof key, ValueType>;
3428

3529
/**
3630
* A callback which is provided by a context requester and is called with the value satisfying the request.
@@ -51,7 +45,7 @@ export type ContextCallback<ValueType> = (
5145
* multiple times if the value is changed, if this is the case the provider should pass an `unsubscribe`
5246
* function to the callback which requesters can invoke to indicate they no longer wish to receive these updates.
5347
*/
54-
export class ContextEvent<T extends UnknownContext> extends Event {
48+
export class ContextRequestEvent<T extends UnknownContext> extends Event {
5549
public constructor(
5650
public readonly context: T,
5751
public readonly callback: ContextCallback<ContextType<T>>,
@@ -67,12 +61,12 @@ export class ContextEvent<T extends UnknownContext> extends Event {
6761
*/
6862
declare global {
6963
interface WindowEventMap {
70-
"context-request": ContextEvent<UnknownContext>;
64+
"context-request": ContextRequestEvent<UnknownContext>;
7165
}
7266
interface ElementEventMap {
73-
"context-request": ContextEvent<UnknownContext>;
67+
"context-request": ContextRequestEvent<UnknownContext>;
7468
}
7569
interface HTMLElementEventMap {
76-
"context-request": ContextEvent<UnknownContext>;
70+
"context-request": ContextRequestEvent<UnknownContext>;
7771
}
7872
}

index.ts

+11-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { ObservableMap } from "./observable-map.js";
22
import {
33
createContext,
4-
ContextEvent,
4+
Context,
5+
ContextRequestEvent,
56
UnknownContext,
67
} from "./context-protocol.js";
78

@@ -27,7 +28,7 @@ export declare type Constructor<T> = new (...args: any[]) => T;
2728

2829
type ProviderElement = CustomElement & {
2930
contexts?: Record<PropertyKey, () => unknown>;
30-
updateContext?(name: string, value: unknown): void;
31+
updateContext?(name: PropertyKey, value: unknown): void;
3132
};
3233

3334
type ConsumerElement = CustomElement & {
@@ -57,18 +58,14 @@ export function ProviderMixin<T extends Constructor<ProviderElement>>(
5758
this.removeEventListener("context-request", this.#handleContextRequest);
5859
}
5960

60-
updateContext(name: string, value: unknown) {
61-
this.#dataStore.set(name, value);
61+
updateContext(name: PropertyKey, value: unknown) {
62+
this.#dataStore.set(createContext(name), value);
6263
}
6364

6465
// We listen for a bubbled context request event and provide the event with the context requested.
65-
#handleContextRequest(event: ContextEvent<UnknownContext>) {
66-
const { name, initialValue } = event.context;
66+
#handleContextRequest(event: ContextRequestEvent<UnknownContext>) {
6767
const subscribe = event.subscribe;
68-
if (initialValue) {
69-
this.#dataStore.set(name, initialValue);
70-
}
71-
const data = this.#dataStore.get(name);
68+
const data = this.#dataStore.get(event.context);
7269
if (data) {
7370
event.stopPropagation();
7471

@@ -93,11 +90,11 @@ export function ConsumerMixin<T extends Constructor<ConsumerElement>>(
9390
return class extends Class {
9491
#unsubscribes: Array<() => void> = [];
9592

96-
getContext(contextName: string) {
97-
let result;
93+
getContext(contextName: PropertyKey) {
94+
let result: unknown;
9895

9996
this.dispatchEvent(
100-
new ContextEvent(createContext(contextName), (data) => {
97+
new ContextRequestEvent(createContext(contextName), (data) => {
10198
result = data;
10299
}),
103100
);
@@ -116,7 +113,7 @@ export function ConsumerMixin<T extends Constructor<ConsumerElement>>(
116113
// reaches a component that is able to provide that value to us.
117114
// The event has a callback for the the value.
118115
this.dispatchEvent(
119-
new ContextEvent(
116+
new ContextRequestEvent(
120117
context,
121118
(data, unsubscribe) => {
122119
callback(data);

observable-map.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
type Subscriber<T> = (value: T) => void;
22

3-
export class ObservableMap {
4-
#store = new Map<string, {value: unknown, subscribers: Set<Subscriber<unknown>>}>
3+
export class ObservableMap<K, V> {
4+
#store = new Map<K, { value: V; subscribers: Set<Subscriber<V>> }>();
55

6-
set(key: string, value: unknown, subscribers = new Set<Subscriber<unknown>>()) {
6+
set(key: K, value: V, subscribers = new Set<Subscriber<V>>()) {
77
const data = this.#store.get(key);
8-
subscribers = new Set([...subscribers, ...(data?.subscribers || new Set())]);
8+
subscribers = new Set([
9+
...subscribers,
10+
...(data?.subscribers || new Set()),
11+
]);
912

10-
this.#store.set(key, {value, subscribers});
13+
this.#store.set(key, { value, subscribers });
1114
for (const subscriber of subscribers) {
1215
subscriber(value);
1316
}
1417
}
1518

16-
get(key: string) {
19+
get(key: K) {
1720
return this.#store.get(key);
1821
}
1922
}

0 commit comments

Comments
 (0)