Skip to content

Commit 3babb43

Browse files
committed
More tweaks and changes
1 parent 7ef83f8 commit 3babb43

10 files changed

+85
-31
lines changed

src/07-advanced-patterns/50-required-context.problem.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22
import { Equal, Expect } from "../helpers/type-utils";
33

4-
const createGenericContext = () => {
4+
const createRequiredContext = () => {
55
const context = React.createContext(null);
66

77
const useContext = () => {
@@ -17,11 +17,11 @@ const createGenericContext = () => {
1717
return [useContext, context.Provider] as const;
1818
};
1919

20-
const [useUser, UserProvider] = createGenericContext<{
20+
const [useUser, UserProvider] = createRequiredContext<{
2121
name: string;
2222
}>();
2323

24-
const [useTheme, ThemeProvider] = createGenericContext<{
24+
const [useTheme, ThemeProvider] = createRequiredContext<{
2525
primaryColor: string;
2626
}>();
2727

src/07-advanced-patterns/50-required-context.solution.1.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22
import { Equal, Expect } from "../helpers/type-utils";
33

4-
const createGenericContext = <T,>() => {
4+
const createRequiredContext = <T,>() => {
55
const context = React.createContext<T | null>(null);
66

77
const useContext = () => {
@@ -17,11 +17,11 @@ const createGenericContext = <T,>() => {
1717
return [useContext, context.Provider] as const;
1818
};
1919

20-
const [useUser, UserProvider] = createGenericContext<{
20+
const [useUser, UserProvider] = createRequiredContext<{
2121
name: string;
2222
}>();
2323

24-
const [useTheme, ThemeProvider] = createGenericContext<{
24+
const [useTheme, ThemeProvider] = createRequiredContext<{
2525
primaryColor: string;
2626
}>();
2727

src/07-advanced-patterns/50-required-context.solution.2.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22
import { Equal, Expect } from "../helpers/type-utils";
33

4-
const createGenericContext = <T,>(): [() => T, React.Provider<T | null>] => {
4+
const createRequiredContext = <T,>(): [() => T, React.Provider<T | null>] => {
55
const context = React.createContext<T | null>(null);
66

77
const useContext = (): T => {
@@ -17,11 +17,11 @@ const createGenericContext = <T,>(): [() => T, React.Provider<T | null>] => {
1717
return [useContext, context.Provider];
1818
};
1919

20-
const [useUser, UserProvider] = createGenericContext<{
20+
const [useUser, UserProvider] = createRequiredContext<{
2121
name: string;
2222
}>();
2323

24-
const [useTheme, ThemeProvider] = createGenericContext<{
24+
const [useTheme, ThemeProvider] = createRequiredContext<{
2525
primaryColor: string;
2626
}>();
2727

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ForwardedRef, forwardRef } from "react";
2+
import { Equal, Expect } from "../helpers/type-utils";
23

34
type Props<T> = {
45
data: T[];
@@ -11,19 +12,20 @@ type Props<T> = {
1112
// ): (props: P & React.RefAttributes<T>) => React.ReactElement | null;
1213
// }
1314

14-
export const Table = forwardRef(
15-
<T,>(props: Props<T>, ref: ForwardedRef<any>) => {
16-
return null;
17-
},
18-
);
15+
export const Table = <T,>(props: Props<T>, ref: ForwardedRef<any>) => {
16+
return null;
17+
};
18+
19+
const ForwardReffedTable = forwardRef(Table);
1920

2021
const Parent = () => {
2122
return (
22-
<Table
23+
<ForwardReffedTable
2324
data={["123"]}
2425
renderRow={(row) => {
26+
type test = Expect<Equal<typeof row, string>>;
2527
return <div>123</div>;
2628
}}
27-
></Table>
29+
></ForwardReffedTable>
2830
);
2931
};
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { ForwardedRef, forwardRef } from "react";
2+
import { Equal, Expect } from "../helpers/type-utils";
3+
4+
type Props<T> = {
5+
data: T[];
6+
renderRow: (item: T) => React.ReactNode;
7+
};
8+
9+
/**
10+
* It even works across module boundaries!
11+
*
12+
* Try uncommenting the declare module section in
13+
* explainer.1.tsx, and watch the error below go away.
14+
*/
15+
export const Table = <T,>(props: Props<T>, ref: ForwardedRef<any>) => {
16+
return null;
17+
};
18+
19+
const ForwardReffedTable = forwardRef(Table);
20+
21+
const Parent = () => {
22+
return (
23+
<ForwardReffedTable
24+
data={["123"]}
25+
renderRow={(row) => {
26+
type test = Expect<Equal<typeof row, string>>;
27+
return <div>123</div>;
28+
}}
29+
></ForwardReffedTable>
30+
);
31+
};
Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
type AsProps = {
2-
[K in keyof JSX.IntrinsicElements]: {
3-
as: K;
4-
} & JSX.IntrinsicElements[K];
5-
}[keyof JSX.IntrinsicElements];
6-
7-
export const Component = (props: AsProps) => {
1+
export const Component = (props: any) => {
82
const Comp = props.as;
93
return <Comp {...(props as any)}></Comp>;
104
};
115

12-
const yeah = <Component as="a" href="awdawd"></Component>;
6+
// Should work, and you should get autocomplete on the
7+
// props for the 'a' tag
8+
const example1 = <Component as="a" href="awdawd"></Component>;
9+
10+
const example2 = (
11+
<Component
12+
as="div"
13+
// @ts-expect-error: Property 'href' does not exist
14+
href="awdawd"
15+
></Component>
16+
);

src/07-advanced-patterns/54-as-prop.solution.1.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const example1 = <Component as="a" href="awdawd"></Component>;
1414
const example2 = (
1515
<Component
1616
as="div"
17-
// Property 'href' does not exist
17+
// @ts-expect-error: Property 'href' does not exist
1818
href="awdawd"
1919
></Component>
2020
);

src/07-advanced-patterns/54-as-prop.solution.2.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,18 @@ export const Component = <TAs extends keyof JSX.IntrinsicElements>(
44
} & JSX.IntrinsicElements[TAs],
55
) => {
66
const Comp = props.as as string;
7-
return <Comp {...(props as any)}></Comp>;
7+
8+
// In this version, we can remove the 'as any' because
9+
// TypeScript is able to keep up with the inference
10+
return <Comp {...props}></Comp>;
811
};
912

10-
const yeah = <Component as="input" value="awd"></Component>;
13+
const example1 = <Component as="a" href="awdawd"></Component>;
14+
15+
const example2 = (
16+
<Component
17+
as="div"
18+
// @ts-expect-error: Property 'href' does not exist
19+
href="awdawd"
20+
></Component>
21+
);
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React from "react";
22

3-
export const Component = (props: { as: any }) => {
3+
export const Component = (props: { as: unknown }) => {
44
const Comp = props.as;
5-
return <Comp {...(props as any)}></Comp>;
5+
return <Comp {...props}></Comp>;
66
};
77

88
const Link = (props: { href: string; children?: React.ReactNode }) => {
99
return <a href={props.href}>{props.children}</a>;
1010
};
1111

12-
const yeah = <Component as={Link} href="awdawd"></Component>;
12+
<Component as={Link} href="awdawd"></Component>;

src/07-advanced-patterns/55-as-prop-with-custom-components.solution.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ export const Component = <
88
} & ComponentProps<T>,
99
) => {
1010
const Comp = props.as;
11-
return <Comp {...(props as any)}></Comp>;
11+
return (
12+
<Comp
13+
// The 'as any' is still needed, because 'as' is SO generic
14+
// that TypeScript can't handle it.
15+
{...props}
16+
></Comp>
17+
);
1218
};
1319

1420
const Link = (props: { href: string; children?: React.ReactNode }) => {

0 commit comments

Comments
 (0)