Skip to content

Commit bc7714a

Browse files
author
David Emanuel Luksic
committed
Typescript: Context.Provider value should not be assignable to undefined in the default case
1 parent e7ea929 commit bc7714a

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

packages/solid/src/reactive/signal.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1130,10 +1130,10 @@ export function registerGraph(value: SourceMapValue): void {
11301130
export type ContextProviderComponent<T> = FlowComponent<{ value: T }>;
11311131

11321132
// Context API
1133-
export interface Context<T> {
1133+
export interface Context<T, D = T> {
11341134
id: symbol;
11351135
Provider: ContextProviderComponent<T>;
1136-
defaultValue: T;
1136+
defaultValue: D;
11371137
}
11381138

11391139
/**
@@ -1158,7 +1158,7 @@ export interface Context<T> {
11581158
export function createContext<T>(
11591159
defaultValue?: undefined,
11601160
options?: EffectOptions
1161-
): Context<T | undefined>;
1161+
): Context<T, undefined>;
11621162
export function createContext<T>(defaultValue: T, options?: EffectOptions): Context<T>;
11631163
export function createContext<T>(
11641164
defaultValue?: T,
@@ -1176,7 +1176,7 @@ export function createContext<T>(
11761176
*
11771177
* @description https://www.solidjs.com/docs/latest/api#usecontext
11781178
*/
1179-
export function useContext<T>(context: Context<T>): T {
1179+
export function useContext<T, D>(context: Context<T, D>): D extends undefined ? T | undefined : T {
11801180
return Owner && Owner.context && Owner.context[context.id] !== undefined
11811181
? Owner.context[context.id]
11821182
: context.defaultValue;
@@ -1215,7 +1215,7 @@ export type SuspenseContextType = {
12151215
resolved?: boolean;
12161216
};
12171217

1218-
type SuspenseContext = Context<SuspenseContextType | undefined> & {
1218+
type SuspenseContext = Context<SuspenseContextType, undefined> & {
12191219
active?(): boolean;
12201220
increment?(): void;
12211221
decrement?(): void;
@@ -1224,7 +1224,7 @@ type SuspenseContext = Context<SuspenseContextType | undefined> & {
12241224
let SuspenseContext: SuspenseContext;
12251225

12261226
export function getSuspenseContext() {
1227-
return SuspenseContext || (SuspenseContext = createContext<SuspenseContextType | undefined>());
1227+
return SuspenseContext || (SuspenseContext = createContext<SuspenseContextType>());
12281228
}
12291229

12301230
// Interop

packages/solid/web/test/context.spec.tsx

+36-13
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ describe("Testing Context", () => {
2020
</Show>
2121
);
2222
};
23-
const div = document.createElement("div");
23+
2424
it("should create context properly", () => {
2525
expect(ThemeContext.id).toBeDefined();
2626
expect(ThemeContext.defaultValue).toBe("light");
2727
});
2828

2929
it("should work with single provider child", () => {
30+
const div = document.createElement("div");
3031
render(
3132
() => (
3233
<ThemeContext.Provider value="dark">
@@ -35,11 +36,11 @@ describe("Testing Context", () => {
3536
),
3637
div
3738
);
38-
expect((div.firstChild as HTMLDivElement).innerHTML).toBe("dark");
39-
div.innerHTML = "";
39+
expect(div.children[0].innerHTML).toBe("dark");
4040
});
4141

4242
it("should work with single conditional provider child", () => {
43+
const div = document.createElement("div");
4344
render(
4445
() => (
4546
<ThemeContext.Provider value="dark">
@@ -48,11 +49,11 @@ describe("Testing Context", () => {
4849
),
4950
div
5051
);
51-
expect((div.firstChild as HTMLDivElement).innerHTML).toBe("dark");
52-
div.innerHTML = "";
52+
expect(div.children[0].innerHTML).toBe("dark");
5353
});
5454

5555
it("should work with multi provider child", () => {
56+
const div = document.createElement("div");
5657
render(
5758
() => (
5859
<ThemeContext.Provider value="dark">
@@ -62,11 +63,11 @@ describe("Testing Context", () => {
6263
),
6364
div
6465
);
65-
expect((div.firstChild!.nextSibling! as HTMLDivElement).innerHTML).toBe("dark");
66-
div.innerHTML = "";
66+
expect(div.children[1].innerHTML).toBe("dark");
6767
});
6868

6969
it("should work with multi conditional provider child", () => {
70+
const div = document.createElement("div");
7071
render(
7172
() => (
7273
<ThemeContext.Provider value="dark">
@@ -76,11 +77,11 @@ describe("Testing Context", () => {
7677
),
7778
div
7879
);
79-
expect((div.firstChild!.nextSibling! as HTMLDivElement).innerHTML).toBe("dark");
80-
div.innerHTML = "";
80+
expect(div.children[1].innerHTML).toBe("dark");
8181
});
8282

8383
it("should work with dynamic multi provider child", () => {
84+
const div = document.createElement("div");
8485
const child = () => <Component />;
8586
render(
8687
() => (
@@ -91,11 +92,11 @@ describe("Testing Context", () => {
9192
),
9293
div
9394
);
94-
expect((div.firstChild!.nextSibling! as HTMLDivElement).innerHTML).toBe("dark");
95-
div.innerHTML = "";
95+
expect(div.children[1].innerHTML).toBe("dark");
9696
});
9797

9898
it("should work with dynamic multi conditional provider child", () => {
99+
const div = document.createElement("div");
99100
const child = () => <CondComponent />;
100101
render(
101102
() => (
@@ -106,7 +107,29 @@ describe("Testing Context", () => {
106107
),
107108
div
108109
);
109-
expect((div.firstChild!.nextSibling! as HTMLDivElement).innerHTML).toBe("dark");
110-
div.innerHTML = "";
110+
expect(div.children[1].innerHTML).toBe("dark");
111+
});
112+
113+
const ThemeContextWithoutDefault = createContext<string>();
114+
const ComponentWithoutDefault = () => {
115+
const theme = useContext(ThemeContextWithoutDefault);
116+
return <div>{theme ?? 'no-default'}</div>;
117+
};
118+
119+
it("should work with no default provided", () => {
120+
const div = document.createElement("div");
121+
render(
122+
() => (
123+
<>
124+
<ComponentWithoutDefault />
125+
<ThemeContextWithoutDefault.Provider value="dark">
126+
<ComponentWithoutDefault />
127+
</ThemeContextWithoutDefault.Provider>
128+
</>
129+
),
130+
div
131+
);
132+
expect(div.children[0].innerHTML!).toBe("no-default");
133+
expect(div.children[1].innerHTML!).toBe("dark");
111134
});
112135
});

0 commit comments

Comments
 (0)