Skip to content

Commit 8291471

Browse files
committed
Added as prop stuff
1 parent 263df0f commit 8291471

File tree

45 files changed

+179
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+179
-21
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
2-
.vscode
2+
.vscode
3+
tsconfig.temp.json

package.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,19 @@
144144
"e-65": "tt-cli run 65",
145145
"s-65": "tt-cli run 65 --solution",
146146
"e-66": "tt-cli run 66",
147-
"s-66": "tt-cli run 66 --solution"
147+
"s-66": "tt-cli run 66 --solution",
148+
"e-43": "tt-cli run 43",
149+
"s-43": "tt-cli run 43 --solution",
150+
"e-67": "tt-cli run 67",
151+
"s-67": "tt-cli run 67 --solution",
152+
"e-68": "tt-cli run 68",
153+
"s-68": "tt-cli run 68 --solution",
154+
"e-70": "tt-cli run 70",
155+
"s-70": "tt-cli run 70 --solution",
156+
"e-71": "tt-cli run 71",
157+
"s-71": "tt-cli run 71 --solution",
158+
"e-73": "tt-cli run 73",
159+
"s-73": "tt-cli run 73 --solution"
148160
},
149161
"dependencies": {
150162
"@tanstack/react-query": "^4.29.12",
@@ -158,4 +170,4 @@
158170
"react-select": "^5.7.3",
159171
"zod": "^3.21.4"
160172
}
161-
}
173+
}

src/08-advanced-patterns/64-forward-ref-with-generics.explainer.1.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ type Props<T> = {
1717

1818
// declare module "react" {
1919
// function forwardRef<T, P = {}>(
20-
// render: (props: P, ref: React.Ref<T>) => React.ReactNode | null,
21-
// ): (props: P & React.RefAttributes<T>) => React.ReactNode | null;
20+
// render: (props: P, ref: React.Ref<T>) => React.ReactNode,
21+
// ): (props: P & React.RefAttributes<T>) => React.ReactNode;
2222
// }
2323

2424
/**
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { ForwardedRef, forwardRef } from "react";
2+
import { Equal, Expect } from "../helpers/type-utils";
3+
4+
/**
5+
* Using the forward-ref-with-generics explanation as a guide,
6+
* give fixedForwardRef a type signature that allows it to
7+
* work with the example below.
8+
*/
9+
function fixedForwardRef(
10+
render: (props: any, ref: any) => any,
11+
): (props: any) => any {
12+
return forwardRef(render) as any;
13+
}
14+
15+
type Props<T> = {
16+
data: T[];
17+
renderRow: (item: T) => React.ReactNode;
18+
};
19+
20+
export const Table = <T,>(props: Props<T>, ref: ForwardedRef<any>) => {
21+
return null;
22+
};
23+
24+
const ForwardReffedTable = fixedForwardRef(Table);
25+
26+
const Parent = () => {
27+
return (
28+
<ForwardReffedTable
29+
data={["123"]}
30+
renderRow={(row) => {
31+
type test = Expect<Equal<typeof row, string>>;
32+
return <div>123</div>;
33+
}}
34+
></ForwardReffedTable>
35+
);
36+
};
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+
function fixedForwardRef<T, P = {}>(
5+
render: (props: P, ref: React.Ref<T>) => React.ReactNode,
6+
): (props: P & React.RefAttributes<T>) => React.ReactNode {
7+
return forwardRef(render) as any;
8+
}
9+
10+
type Props<T> = {
11+
data: T[];
12+
renderRow: (item: T) => React.ReactNode;
13+
};
14+
15+
export const Table = <T,>(props: Props<T>, ref: ForwardedRef<any>) => {
16+
return null;
17+
};
18+
19+
const ForwardReffedTable = fixedForwardRef(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+
};

src/08-advanced-patterns/68-as-prop-with-custom-components.solution.tsx

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React, { ComponentPropsWithoutRef, ElementType } from "react";
2+
import { Equal, Expect } from "../helpers/type-utils";
3+
4+
export const Wrapper = <T extends ElementType<any>>(
5+
props: {
6+
as: T;
7+
} & ComponentPropsWithoutRef<T>,
8+
) => {
9+
const Comp = props.as;
10+
return <Comp {...(props as any)}></Comp>;
11+
};
12+
13+
const Link = (props: { href: string; children?: React.ReactNode }) => {
14+
return <a href={props.href}>{props.children}</a>;
15+
};
16+
17+
<Wrapper as={Link} href="awdawd" />;
18+
<Wrapper
19+
as="button"
20+
onClick={(e) => {
21+
type test = Expect<Equal<typeof e, React.MouseEvent<HTMLButtonElement>>>;
22+
}}
23+
/>;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { ComponentPropsWithoutRef, ElementType } from "react";
2+
import { Equal, Expect } from "../helpers/type-utils";
3+
4+
export const Link = <T extends ElementType<any>>(
5+
props: {
6+
as: T;
7+
} & ComponentPropsWithoutRef<T>,
8+
) => {
9+
const { as: Comp, ...rest } = props;
10+
return <Comp {...rest}></Comp>;
11+
};
12+
13+
// Should be a 'a' tag by default!
14+
<Link href="/"></Link>;
15+
16+
const Custom = (props: { thisIsRequired: boolean }) => {
17+
return null;
18+
};
19+
20+
<Link as={Custom} thisIsRequired />;
21+
22+
// @ts-expect-error Property 'thisIsRequired' is missing
23+
<Link as={Custom} />;
24+
25+
<Link
26+
as="button"
27+
onClick={(e) => {
28+
type test = Expect<Equal<typeof e, React.MouseEvent<HTMLButtonElement>>>;
29+
}}
30+
></Link>;
31+
32+
<Link
33+
as="div"
34+
// @ts-expect-error: Property 'href' does not exist
35+
href="awdawd"
36+
></Link>;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { ComponentPropsWithoutRef, ElementType } from "react";
2+
import { Equal, Expect } from "../helpers/type-utils";
3+
4+
export const Link = <T extends ElementType<any> = "a">(
5+
props: {
6+
as?: T;
7+
} & ComponentPropsWithoutRef<T>,
8+
) => {
9+
const { as: Comp = "a", ...rest } = props;
10+
return <Comp {...rest}></Comp>;
11+
};
12+
13+
<Link href="/"></Link>;
14+
15+
const Custom = (props: { thisIsRequired: boolean }) => {
16+
return null;
17+
};
18+
19+
<Link as={Custom} thisIsRequired />;
20+
21+
// @ts-expect-error Property 'thisIsRequired' is missing
22+
<Link as={Custom} />;
23+
24+
<Link
25+
as="button"
26+
onClick={(e) => {
27+
type test = Expect<Equal<typeof e, React.MouseEvent<HTMLButtonElement>>>;
28+
}}
29+
></Link>;
30+
31+
<Link
32+
as="div"
33+
// @ts-expect-error: Property 'href' does not exist
34+
href="awdawd"
35+
></Link>;

0 commit comments

Comments
 (0)