Skip to content

Commit c08e41c

Browse files
author
Mansur Isakov
committed
feat: advanced hooks solutions
1 parent 4806540 commit c08e41c

8 files changed

+43
-18
lines changed

src/06-advanced-hooks/45-tuple-return-type.problem.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import { Equal, Expect } from "../helpers/type-utils";
1111
* 1. Find a way to fix the errors below.
1212
*/
1313

14-
export const useId = (defaultId: string) => {
14+
export const useId = (
15+
defaultId: string
16+
): [string, React.Dispatch<React.SetStateAction<string>>] => {
1517
const [id, setId] = useState(defaultId);
1618

1719
return [id, setId];
@@ -21,5 +23,5 @@ const [id, setId] = useId("1");
2123

2224
type tests = [
2325
Expect<Equal<typeof id, string>>,
24-
Expect<Equal<typeof setId, React.Dispatch<React.SetStateAction<string>>>>,
26+
Expect<Equal<typeof setId, React.Dispatch<React.SetStateAction<string>>>>
2527
];

src/06-advanced-hooks/46-required-context.problem.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import { Equal, Expect } from "../helpers/type-utils";
1414
*
1515
* 1. See if you can fix it!
1616
*/
17-
const createRequiredContext = () => {
18-
const context = React.createContext(null);
17+
const createRequiredContext = <T,>() => {
18+
const context = React.createContext<T | null>(null);
1919

2020
const useContext = () => {
2121
const contextValue = React.useContext(context);
@@ -27,7 +27,7 @@ const createRequiredContext = () => {
2727
return contextValue;
2828
};
2929

30-
return [useContext, context.Provider];
30+
return [useContext, context.Provider] as const;
3131
};
3232

3333
const [useUser, UserProvider] = createRequiredContext<{

src/06-advanced-hooks/47-unions-in-usestate.problem.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ import { appendVideoToDomAndPlay, fetchVideo } from "fake-external-lib";
1212
*
1313
* 1. See if you can fix the errors below by making the type of state more specific.
1414
*/
15+
type State = "loading" | "loaded" | "error";
16+
1517
export const useLoadAsyncVideo = (src: string) => {
16-
const [state, setState] = useState("loading");
18+
const [state, setState] = useState<State>("loading");
1719

1820
useEffect(() => {
1921
setState("loading");

src/06-advanced-hooks/48-discriminated-unions-in-usestate.problem.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
import { appendVideoToDomAndPlay, fetchVideo } from "fake-external-lib";
22
import { useEffect, useState } from "react";
33

4+
type Status =
5+
| {
6+
status: "error";
7+
error: Error;
8+
}
9+
| {
10+
status: "loading" | "loaded";
11+
};
12+
413
export const useLoadAsyncVideo = (src: string) => {
5-
const [state, setState] = useState({
14+
const [state, setState] = useState<Status>({
615
status: "loading",
716
});
817

src/06-advanced-hooks/49-discriminated-tuples-from-custom-hooks.problem.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { useEffect, useState } from "react";
22

3-
export type Result<T> = [
4-
"loading" | "success" | "error",
5-
T | Error | undefined,
6-
];
3+
export type Result<T> =
4+
| ["loading", undefined]
5+
| ["success", T]
6+
| ["error", Error];
77

88
/**
99
* Let's look at one more example of discriminated unions. This time, we're
@@ -35,7 +35,7 @@ export const useData = <T,>(url: string): Result<T> => {
3535

3636
const Component = () => {
3737
const [status, value] = useData<{ title: string }>(
38-
"https://jsonplaceholder.typicode.com/todos/1",
38+
"https://jsonplaceholder.typicode.com/todos/1"
3939
);
4040

4141
if (status === "loading") {

src/06-advanced-hooks/50-use-state-overloads.problem.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ useState;
1919
* HINT - you'll need to use the function keyword THREE times.
2020
*/
2121

22+
function maybeReturnsString(defaultString: string): string;
23+
function maybeReturnsString(): undefined | string;
2224
function maybeReturnsString(defaultString?: string) {
2325
// If you pass a string, it always returns a string
2426
if (defaultString) {
@@ -34,5 +36,5 @@ const example2 = maybeReturnsString();
3436

3537
type tests = [
3638
Expect<Equal<typeof example1, string>>,
37-
Expect<Equal<typeof example2, string | undefined>>,
39+
Expect<Equal<typeof example2, string | undefined>>
3840
];

src/06-advanced-hooks/51-function-overloads-in-hooks.problem.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ import { Equal, Expect } from "../helpers/type-utils";
77
*
88
* If you pass a default value, it should NOT include undefined.
99
*/
10-
export function useStateAsObject<T>(initial: T) {
10+
type UseStateReturnValue<T> = {
11+
value: T;
12+
set: React.Dispatch<React.SetStateAction<T>>;
13+
};
14+
15+
export function useStateAsObject<T>(): UseStateReturnValue<T | undefined>;
16+
export function useStateAsObject<T>(initial: T): UseStateReturnValue<T>;
17+
export function useStateAsObject<T>(initial?: T) {
1118
const [value, set] = useState(initial);
1219

1320
return {
@@ -28,7 +35,7 @@ type ExampleTests = [
2835
typeof notUndefined.set,
2936
React.Dispatch<React.SetStateAction<{ name: string }>>
3037
>
31-
>,
38+
>
3239
];
3340

3441
/**
@@ -43,5 +50,5 @@ type NumTests = [
4350
typeof hasUndefined.set,
4451
React.Dispatch<React.SetStateAction<number | undefined>>
4552
>
46-
>,
53+
>
4754
];

src/06-advanced-hooks/52-currying-hooks.problem.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ const useCustomState = <TValue>(initial: TValue) => {
1515
* any type. We want to make sure that the type of the
1616
* thing returned is inferred properly.
1717
*/
18-
useComputed: (factory: (value: any) => any, deps?: DependencyList) => {
18+
useComputed: <TResult>(
19+
factory: (value: TValue) => TResult,
20+
deps?: DependencyList
21+
) => {
1922
return useMemo(() => {
2023
return factory(value);
2124
}, [value, ...(deps || [])]);
@@ -32,7 +35,7 @@ const Component = () => {
3235
* useComputed?
3336
*/
3437
const reversedAsString = arrayOfNums.useComputed((nums) =>
35-
Array.from(nums).reverse().map(String),
38+
Array.from(nums).reverse().map(String)
3639
);
3740

3841
type test = Expect<Equal<typeof reversedAsString, string[]>>;

0 commit comments

Comments
 (0)