Skip to content

Commit 1b708f6

Browse files
committed
Added 27, modified 26
1 parent 8ff732b commit 1b708f6

28 files changed

+213
-42
lines changed
Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,28 @@
1-
// TODO
1+
const presetSizes = {
2+
xs: "0.5rem",
3+
sm: "1rem",
4+
};
5+
6+
type Size = keyof typeof presetSizes;
7+
8+
type LooseSize = Size | string;
9+
10+
export const Icon = (props: { size: LooseSize }) => {
11+
return (
12+
<div
13+
style={{
14+
width:
15+
props.size in presetSizes
16+
? presetSizes[props.size as Size]
17+
: props.size,
18+
}}
19+
/>
20+
);
21+
};
22+
23+
<>
24+
{/* Autocomplete for sm and xs are no longer working! */}
25+
<Icon size="sm"></Icon>
26+
<Icon size="xs"></Icon>
27+
<Icon size="10px"></Icon>
28+
</>;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const presetSizes = {
2+
xs: "0.5rem",
3+
sm: "1rem",
4+
};
5+
6+
type Size = keyof typeof presetSizes;
7+
8+
type LooseSize = Size | (string & {});
9+
10+
export const Icon = (props: { size: LooseSize }) => {
11+
return (
12+
<div
13+
style={{
14+
width:
15+
props.size in presetSizes
16+
? presetSizes[props.size as Size]
17+
: props.size,
18+
}}
19+
/>
20+
);
21+
};
22+
23+
<>
24+
<Icon size="sm"></Icon>
25+
<Icon size="xs"></Icon>
26+
<Icon size="10px"></Icon>
27+
</>;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const presetSizes = {
2+
xs: "0.5rem",
3+
sm: "1rem",
4+
};
5+
6+
type Size = keyof typeof presetSizes;
7+
8+
type LooseAutocomplete<T> = T | (string & {});
9+
10+
type LooseSize = LooseAutocomplete<Size>;
11+
12+
export const Icon = (props: { size: LooseSize }) => {
13+
return (
14+
<div
15+
style={{
16+
width:
17+
props.size in presetSizes
18+
? presetSizes[props.size as Size]
19+
: props.size,
20+
}}
21+
/>
22+
);
23+
};
24+
25+
<>
26+
<Icon size="sm"></Icon>
27+
<Icon size="xs"></Icon>
28+
<Icon size="10px"></Icon>
29+
</>;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Equal, Expect } from "../helpers/type-utils";
2+
3+
type InputProps = React.ComponentProps<"input">;
4+
5+
/**
6+
* All these components take the same props!
7+
*
8+
* We don't want to repeat ourselves by typing
9+
* props: InputProps for each component.
10+
*
11+
* There must be a better way!
12+
*
13+
* Hint: Record and satisfies will come in handy.
14+
*/
15+
const COMPONENTS = {
16+
text: (props) => {
17+
return <input {...props} type="text" />;
18+
},
19+
number: (props) => {
20+
return <input {...props} type="number" />;
21+
},
22+
password: (props) => {
23+
return <input {...props} type="password" />;
24+
},
25+
};
26+
27+
export const Input = (props: unknown) => {
28+
const Component = COMPONENTS[props.type];
29+
return <Component {...props} />;
30+
};
31+
32+
<>
33+
<Input
34+
type="number"
35+
onChange={(e) => {
36+
// e should be properly typed!
37+
type test = Expect<Equal<typeof e, React.ChangeEvent<HTMLInputElement>>>;
38+
}}
39+
></Input>
40+
<Input type="text"></Input>
41+
<Input type="password"></Input>
42+
43+
{/* @ts-expect-error */}
44+
<Input type="email"></Input>
45+
</>;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Equal, Expect } from "../helpers/type-utils";
2+
3+
type InputProps = React.ComponentProps<"input">;
4+
5+
type Input = "text" | "number" | "password";
6+
7+
/**
8+
* We can do it by typing Input and making COMPONENTS
9+
* restricted to only those inputs.
10+
*/
11+
const COMPONENTS: Record<Input, React.FC<InputProps>> = {
12+
text: (props) => {
13+
return <input {...props} type="text" />;
14+
},
15+
number: (props) => {
16+
return <input {...props} type="number" />;
17+
},
18+
password: (props) => {
19+
return <input {...props} type="password" />;
20+
},
21+
};
22+
23+
export const Input = (props: { type: Input } & InputProps) => {
24+
const Component = COMPONENTS[props.type];
25+
return <Component {...props} />;
26+
};
27+
28+
<>
29+
<Input
30+
type="number"
31+
onChange={(e) => {
32+
type test = Expect<Equal<typeof e, React.ChangeEvent<HTMLInputElement>>>;
33+
}}
34+
></Input>
35+
<Input type="text"></Input>
36+
<Input type="password"></Input>
37+
38+
{/* @ts-expect-error */}
39+
<Input type="email"></Input>
40+
</>;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Equal, Expect } from "../helpers/type-utils";
2+
3+
type InputProps = React.ComponentProps<"input">;
4+
5+
/**
6+
* OR, we can do it by making COMPONENTS 'satisfy'
7+
* a type that is a Record of React.FC<InputProps>.
8+
*/
9+
const COMPONENTS = {
10+
text: (props) => {
11+
return <input {...props} type="text" />;
12+
},
13+
number: (props) => {
14+
return <input {...props} type="number" />;
15+
},
16+
password: (props) => {
17+
return <input {...props} type="password" />;
18+
},
19+
} satisfies Record<string, React.FC<InputProps>>;
20+
21+
/**
22+
* Then, we can derive the type of input from the
23+
* keys of COMPONENTS.
24+
*/
25+
type Input = keyof typeof COMPONENTS;
26+
27+
export const Input = (props: { type: Input } & InputProps) => {
28+
const Component = COMPONENTS[props.type];
29+
return <Component {...props} />;
30+
};
31+
32+
<>
33+
<Input
34+
type="number"
35+
onChange={(e) => {
36+
type test = Expect<Equal<typeof e, React.ChangeEvent<HTMLInputElement>>>;
37+
}}
38+
></Input>
39+
<Input type="text"></Input>
40+
<Input type="password"></Input>
41+
42+
{/* @ts-expect-error */}
43+
<Input type="email"></Input>
44+
</>;

src/05-advanced-hooks/32-typing-custom-hooks.problem.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/05-advanced-hooks/32-typing-custom-hooks.solution.1.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/05-advanced-hooks/32-typing-custom-hooks.solution.2.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/05-advanced-hooks/32-typing-custom-hooks.solution.3.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/07-advanced-patterns/59-record-of-components-with-same-props.problem.tsx

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)