/**
* Type the HTTPHeaders object so that it has an `Authentication`
* property that starts with `Bearer ` and ends with a JWT token.
*
* Note: JWT tokens contain 3 parts, separated by dots.
* More info on https://jwt.io
*
* Hint: You shouldn't need a conditional type.
*/
namespace headers {
type HTTPHeaders = {
Authentication: `Bearer ${string}.${string}.${string}`
};
const test1: HTTPHeaders = {
// ✅ This is a correct authentication header:
Authentication:
"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtIjoiWW91J3JlIGEgbmVyZCA7KSJ9.gfB7ECp1ePeIB4Mh_3Ypci4y7jFjMH9w_BB4rZcMvQM",
};
const test2: HTTPHeaders = {
// @ts-expect-error: ❌ Authentication should start with 'Bearer'
Authentication: "a.b.c",
};
const test3: HTTPHeaders = {
// @ts-expect-error: ❌ Authentication should start with 'Bearer'
Authentication: "oops a.b.c",
};
const test4: HTTPHeaders = {
// @ts-expect-error: ❌ token is invalid, only 1 part.
Authentication: "Bearer abc",
};
const test5: HTTPHeaders = {
// @ts-expect-error: ❌ token is invalid, only 2 parts.
Authentication: "Bearer abc.123",
};
}
/**
* Implement a `IsYelling` generic that returns
* true if the input string is in all caps and
* false otherwise.
*
* You shouldn't need recursion to solve this one.
*/
namespace isYelling {
type IsYelling<Str extends string> = Str extends Uppercase<Str> ? true : false;
type res1 = IsYelling<"HELLO">;
type test1 = Expect<Equal<res1, true>>;
type res2 = IsYelling<"Hello">;
type test2 = Expect<Equal<res2, false>>;
type res3 = IsYelling<"I am Groot">;
type test3 = Expect<Equal<res3, false>>;
type res4 = IsYelling<"YEAAAH">;
type test4 = Expect<Equal<res4, true>>;
}
/**
* Implement a `StartsWith` generic that takes
* 2 string literals, and returns true if the
* first string starts with the second one.
*/
namespace startsWith {
type StartsWith<Str, Start extends string> = Str extends `${Start}${string}`
? true
: false;
type res1 = StartsWith<"getUsers", "get">;
type test1 = Expect<Equal<res1, true>>;
type res2 = StartsWith<"getArticles", "post">;
type test2 = Expect<Equal<res2, false>>;
type res3 = StartsWith<"Type-Level Programming!", "Type">;
type test3 = Expect<Equal<res3, true>>;
}
삽질했는디.. 답은 엄청 심플하게 끝나네
/**
* Write a type-level function that transforms
* snake_case strings into camelCase.
*/
namespace snakeToCamel {
// 1. _로 나누기
// 2. 두 번째 원소부터 Capitalize
// 3. concat
type SplitByUnderscore<
Str extends string,
Output extends string[] = [],
> = Str extends `${infer First}_${infer Rest}`
? SplitByUnderscore<Rest, [...Output, First]>
: [...Output, Str];
type myRes1 = SplitByUnderscore<"a_b_c_d">;
type myTest1 = Expect<Equal<myRes1, ["a", "b", "c", "d"]>>;
type CapitalizeAll<
Strings extends string[],
Output extends string[] = [],
> = Strings extends [
infer Head extends string,
...infer Rest extends string[],
]
? CapitalizeAll<Rest, [...Output, Capitalize<Head>]>
: Output;
type myRes2 = CapitalizeAll<["test", "capitalize", "all"]>;
type myTest2 = Expect<Equal<myRes2, ["Test", "Capitalize", "All"]>>;
type JoinAll<
Strings extends string[],
Output extends string = "",
> = Strings extends [
infer Head extends string,
...infer Rest extends string[],
]
? JoinAll<Rest, `${Output}${Head}`>
: Output;
type myRes3 = JoinAll<["Test", "Capitalize", "All"]>;
type myTest3 = Expect<Equal<myRes3, "TestCapitalizeAll">>;
type SnakeToCamel<Str extends string> = Uncapitalize<
JoinAll<CapitalizeAll<SplitByUnderscore<Str>>>
>;
// it should let strings with no underscore in them unchanged
type res1 = SnakeToCamel<"hello">;
type test1 = Expect<Equal<res1, "hello">>;
// one underscore
type res2 = SnakeToCamel<"hello_world">;
type test2 = Expect<Equal<res2, "helloWorld">>;
// many underscores
type res3 = SnakeToCamel<"hello_type_level_type_script">;
type test3 = Expect<Equal<res3, "helloTypeLevelTypeScript">>;
}
/**
* Re-implement `SpacesToUnderscores` by defining a `Split`
* and a `Join` generic that behaves like the value-level
* `.split(separator)` and `.join(separator)` methods.
*/
namespace splitAndJoin {
type SpacesToUnderscores<Str> = Join<Split<Str, " ">, "_">;
type Split<
Str,
Separator extends string,
> = Str extends `${infer Head}${Separator}${infer Tail}`
? [Head, ...Split<Tail, Separator>]
: [Str];
type Join<List, Separator extends string> = List extends [
infer Head extends string,
...infer Tail extends string[],
]
? Tail["length"] extends 0
? `${Head}`
: `${Head}${Separator}${Join<Tail, Separator>}`
: "";
type res1 = Split<"a.b.c", ".">;
type test1 = Expect<Equal<res1, ["a", "b", "c"]>>;
type res2 = Join<["a", "b", "c"], ".">;
type test2 = Expect<Equal<res2, "a.b.c">>;
type res3 = SpacesToUnderscores<"hey">;
type test3 = Expect<Equal<res3, "hey">>;
type res4 = SpacesToUnderscores<"user name">;
type test4 = Expect<Equal<res4, "user_name">>;
type res5 = SpacesToUnderscores<"type level typescript">;
type test5 = Expect<Equal<res5, "type_level_typescript">>;
}
보너스 문제는 스킵…