Skip to content

Commit dbafb32

Browse files
committed
Finished 'as' work
1 parent 8c4fe97 commit dbafb32

10 files changed

+681
-177
lines changed

src/08-advanced-patterns/70-as-prop.problem.tsx

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,59 @@
2222
* - Indexed access types
2323
*/
2424

25+
import { Equal, Expect } from "../helpers/type-utils";
26+
2527
export const Wrapper = (props: any) => {
2628
const Comp = props.as;
2729
return <Comp {...(props as any)}></Comp>;
2830
};
2931

30-
// Should work, and you should get autocomplete on the
31-
// props for the 'a' tag
32-
const example1 = <Wrapper as="a" href="awdawd"></Wrapper>;
33-
34-
const example2 = (
35-
<Wrapper
36-
as="div"
37-
// @ts-expect-error: Property 'href' does not exist
38-
href="awdawd"
39-
></Wrapper>
40-
);
32+
/**
33+
* Should work specifying a 'button'
34+
*/
35+
36+
const Example1 = () => {
37+
return (
38+
<>
39+
<Wrapper
40+
as="button"
41+
// @ts-expect-error doesNotExist is not a valid prop
42+
doesNotExist
43+
></Wrapper>
44+
45+
<Wrapper
46+
as="button"
47+
// e should be inferred correctly
48+
onClick={(e) => {
49+
type test = Expect<
50+
Equal<typeof e, React.MouseEvent<HTMLButtonElement>>
51+
>;
52+
}}
53+
></Wrapper>
54+
</>
55+
);
56+
};
57+
58+
/**
59+
* Should work specifying a 'div'
60+
*/
61+
62+
const Example2 = () => {
63+
return (
64+
<>
65+
<Wrapper
66+
as="div"
67+
// @ts-expect-error doesNotExist is not a valid prop
68+
doesNotExist
69+
></Wrapper>
70+
71+
<Wrapper
72+
as="div"
73+
// e should be inferred correctly
74+
onClick={(e) => {
75+
type test = Expect<Equal<typeof e, React.MouseEvent<HTMLDivElement>>>;
76+
}}
77+
></Wrapper>
78+
</>
79+
);
80+
};
Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Equal, Expect } from "../helpers/type-utils";
2+
13
type AsProps = {
24
[K in keyof JSX.IntrinsicElements]: {
35
as: K;
@@ -9,12 +11,52 @@ export const Wrapper = (props: AsProps) => {
911
return <Comp {...(props as any)}></Comp>;
1012
};
1113

12-
const example1 = <Wrapper as="a" href="awdawd"></Wrapper>;
14+
/**
15+
* Should work specifying a 'button'
16+
*/
17+
18+
const Example1 = () => {
19+
return (
20+
<>
21+
<Wrapper
22+
as="button"
23+
// @ts-expect-error doesNotExist is not a valid prop
24+
doesNotExist
25+
></Wrapper>
26+
27+
<Wrapper
28+
as="button"
29+
// e should be inferred correctly
30+
onClick={(e) => {
31+
type test = Expect<
32+
Equal<typeof e, React.MouseEvent<HTMLButtonElement>>
33+
>;
34+
}}
35+
></Wrapper>
36+
</>
37+
);
38+
};
1339

14-
const example2 = (
15-
<Wrapper
16-
as="div"
17-
// @ts-expect-error: Property 'href' does not exist
18-
href="awdawd"
19-
></Wrapper>
20-
);
40+
/**
41+
* Should work specifying a 'div'
42+
*/
43+
44+
const Example2 = () => {
45+
return (
46+
<>
47+
<Wrapper
48+
as="div"
49+
// @ts-expect-error doesNotExist is not a valid prop
50+
doesNotExist
51+
></Wrapper>
52+
53+
<Wrapper
54+
as="div"
55+
// e should be inferred correctly
56+
onClick={(e) => {
57+
type test = Expect<Equal<typeof e, React.MouseEvent<HTMLDivElement>>>;
58+
}}
59+
></Wrapper>
60+
</>
61+
);
62+
};
Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Equal, Expect } from "../helpers/type-utils";
2+
13
export const Wrapper = <TAs extends keyof JSX.IntrinsicElements>(
24
props: {
35
as: TAs;
@@ -8,12 +10,52 @@ export const Wrapper = <TAs extends keyof JSX.IntrinsicElements>(
810
return <Comp {...(props as any)}></Comp>;
911
};
1012

11-
const example1 = <Wrapper as="a" href="awdawd"></Wrapper>;
13+
/**
14+
* Should work specifying a 'button'
15+
*/
16+
17+
const Example1 = () => {
18+
return (
19+
<>
20+
<Wrapper
21+
as="button"
22+
// @ts-expect-error doesNotExist is not a valid prop
23+
doesNotExist
24+
></Wrapper>
25+
26+
<Wrapper
27+
as="button"
28+
// e should be inferred correctly
29+
onClick={(e) => {
30+
type test = Expect<
31+
Equal<typeof e, React.MouseEvent<HTMLButtonElement>>
32+
>;
33+
}}
34+
></Wrapper>
35+
</>
36+
);
37+
};
1238

13-
const example2 = (
14-
<Wrapper
15-
as="div"
16-
// @ts-expect-error: Property 'href' does not exist
17-
href="awdawd"
18-
></Wrapper>
19-
);
39+
/**
40+
* Should work specifying a 'div'
41+
*/
42+
43+
const Example2 = () => {
44+
return (
45+
<>
46+
<Wrapper
47+
as="div"
48+
// @ts-expect-error doesNotExist is not a valid prop
49+
doesNotExist
50+
></Wrapper>
51+
52+
<Wrapper
53+
as="div"
54+
// e should be inferred correctly
55+
onClick={(e) => {
56+
type test = Expect<Equal<typeof e, React.MouseEvent<HTMLDivElement>>>;
57+
}}
58+
></Wrapper>
59+
</>
60+
);
61+
};

src/08-advanced-patterns/71-as-prop-with-custom-components.problem.tsx

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

34
/**
45
* This is a further extension of 'as'. This time, we can pass in
@@ -14,8 +15,55 @@ export const Wrapper = (props: { as: unknown }) => {
1415
return <Comp {...props}></Comp>;
1516
};
1617

17-
const Link = (props: { href: string; children?: React.ReactNode }) => {
18-
return <a href={props.href}>{props.children}</a>;
18+
/**
19+
* Should work specifying a 'button'
20+
*/
21+
22+
const Example1 = () => {
23+
return (
24+
<>
25+
<Wrapper
26+
as="button"
27+
// @ts-expect-error doesNotExist is not a valid prop
28+
doesNotExist
29+
></Wrapper>
30+
31+
<Wrapper
32+
as="button"
33+
// e should be inferred correctly
34+
onClick={(e) => {
35+
type test = Expect<
36+
Equal<typeof e, React.MouseEvent<HTMLButtonElement>>
37+
>;
38+
}}
39+
></Wrapper>
40+
</>
41+
);
1942
};
2043

21-
<Wrapper as={Link} href="awdawd"></Wrapper>;
44+
/**
45+
* Should work with Custom components!
46+
*/
47+
48+
const Custom = (
49+
props: { thisIsRequired: boolean },
50+
ref: React.ForwardedRef<HTMLAnchorElement>,
51+
) => {
52+
return <a ref={ref} />;
53+
};
54+
55+
const Example2 = () => {
56+
return (
57+
<>
58+
<Wrapper as={Custom} thisIsRequired />
59+
<Wrapper
60+
as={Custom}
61+
// @ts-expect-error incorrectProp should not be allowed
62+
incorrectProp
63+
/>
64+
65+
{/* @ts-expect-error thisIsRequired is not being passed */}
66+
<Wrapper as={Custom}></Wrapper>
67+
</>
68+
);
69+
};

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

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,55 @@ export const Wrapper = <T extends ElementType>(
1010
return <Comp {...(props as any)}></Comp>;
1111
};
1212

13-
const Link = (props: { href: string; children?: React.ReactNode }) => {
14-
return <a href={props.href}>{props.children}</a>;
13+
/**
14+
* Should work specifying a 'button'
15+
*/
16+
17+
const Example1 = () => {
18+
return (
19+
<>
20+
<Wrapper
21+
as="button"
22+
// @ts-expect-error doesNotExist is not a valid prop
23+
doesNotExist
24+
></Wrapper>
25+
26+
<Wrapper
27+
as="button"
28+
// e should be inferred correctly
29+
onClick={(e) => {
30+
type test = Expect<
31+
Equal<typeof e, React.MouseEvent<HTMLButtonElement>>
32+
>;
33+
}}
34+
></Wrapper>
35+
</>
36+
);
37+
};
38+
39+
/**
40+
* Should work with Custom components!
41+
*/
42+
43+
const Custom = (
44+
props: { thisIsRequired: boolean },
45+
ref: React.ForwardedRef<HTMLAnchorElement>,
46+
) => {
47+
return <a ref={ref} />;
1548
};
1649

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-
/>;
50+
const Example2 = () => {
51+
return (
52+
<>
53+
<Wrapper as={Custom} thisIsRequired />
54+
<Wrapper
55+
as={Custom}
56+
// @ts-expect-error incorrectProp should not be allowed
57+
incorrectProp
58+
/>
59+
60+
{/* @ts-expect-error thisIsRequired is not being passed */}
61+
<Wrapper as={Custom}></Wrapper>
62+
</>
63+
);
64+
};

0 commit comments

Comments
 (0)