Created
August 5, 2022 20:05
-
-
Save giokaxo/70e0610ecf9d45633373098062b201ff to your computer and use it in GitHub Desktop.
Typescript challenges
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // type First<T extends unknown[]> = T extends { length: 0 } ? never : T[0]; | |
| // type arr1 = ['a', 'b', 'c'] | |
| // type arr2 = [3, 2, 1] | |
| // type head1 = First<arr1> // expected to be 'a' | |
| // type head2 = First<arr2> // expected to be 3 | |
| // type Length<T extends unknown[]> = T['length']; | |
| // type tesla = ['tesla', 'model 3', 'model X', 'model Y'] | |
| // type spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT'] | |
| // type teslaLength = Length<tesla> // expected 4 | |
| // type spaceXLength = Length<spaceX> // expected 5 | |
| // type MyExclude<T, K> = T extends K ? never : T; | |
| // type From = 'a' | 'b' | 'c'; | |
| // type Result = MyExclude<From, 'a'> // 'b' | 'c' | |
| // type If<C extends true | false, T, F> = C extends true ? T : F; | |
| // type A = If<true, 'a', 'b'> // expected to be 'a' | |
| // type B = If<false, 'a', 'b'> // expected to be 'b' | |
| // type Push<T extends unknown[], E> = [...T, E]; | |
| // type Result = Push<[1, 2], '3'> // [1, 2, '3'] | |
| // type Concat<T extends unknown[], E extends unknown[]> = [...T, ...E]; | |
| // type Result = Concat<[1], [2]> // expected to be [1, 2] | |
| // type MyReturnType<T> = T extends (...args: any) => infer R ? R : never; | |
| // const fn = (v: boolean) => { | |
| // if (v) | |
| // return 1 | |
| // else | |
| // return 2 | |
| // } | |
| // type a = MyReturnType<typeof fn> // should be "1 | 2" | |
| // type MyExclude<T, K> = T extends K ? never : T; | |
| // type MyOmit<T, K extends keyof T> = { | |
| // [U in MyExclude<keyof T, K>]: T[U] | |
| // }; | |
| // interface Todo { | |
| // title: string | |
| // description: string | |
| // completed: boolean | |
| // } | |
| // type TodoPreview = MyOmit<Todo, 'description' | 'title'> | |
| // const todo: TodoPreview = { | |
| // completed: false, | |
| // } | |
| // type Last<T extends unknown[]> = T extends [...infer R, infer L] ? L : never; | |
| // type arr1 = ['a', 'b', 'c'] | |
| // type arr2 = [3, 2, 1] | |
| // type tail1 = Last<arr1> // expected to be 'c' | |
| // type tail2 = Last<arr2> // expected to be 1 | |
| // type Pop<T extends unknown[]> = T extends [...infer R, infer L] ? R : never; | |
| // type arr1 = ['a', 'b', 'c', 'd'] | |
| // type arr2 = [3, 2, 1] | |
| // type re1 = Pop<arr1> // expected to be ['a', 'b', 'c'] | |
| // type re2 = Pop<arr2> // expected to be [3, 2] | |
| // type Flatten<T extends unknown[]> = T extends [infer L, ...infer R] | |
| // ? L extends unknown[] | |
| // ? [...Flatten<L>, ...Flatten<R>] | |
| // : [L, ...Flatten<R>] | |
| // : T; | |
| // type flatten = Flatten<[1, 2, [3, 4], [[[5]]]]> // [1, 2, 3, 4, 5] | |
| // type AppendToObject<T extends object, K extends string | number | symbol, V> = Record<K | keyof T, V> | |
| // type Test = { id: '1' } | |
| // type Result = AppendToObject<Test, 'value', 4> // expected to be { id: '1', value: 4 } | |
| // type Merge<F, S> = { | |
| // [K in keyof F | keyof S]: K extends keyof S ? S[K] : K extends keyof F ? F[K] : never | |
| // }; | |
| // type foo = { | |
| // name: string; | |
| // age: string; | |
| // } | |
| // type coo = { | |
| // age: number; | |
| // sex: string | |
| // } | |
| // type Result = Merge<foo, coo>; // expected to be {name: string, age: number, sex: string} | |
| // type MyCapitalize<T extends string> = T extends `${infer F}${infer R}` ? `${Uppercase<F>}${R}` : never; | |
| // type capitalized = MyCapitalize<'hello world'> // expected to be 'Hello world' | |
| // type ReplaceAll<Word extends string, From extends string, To extends string> = | |
| // Word extends `${infer F}${infer R}` ? | |
| // F extends From ? | |
| // `${To}${ReplaceAll<R, From, To>}` : | |
| // `${F}${ReplaceAll<R, From, To>}` : | |
| // Word; | |
| // type replaced = ReplaceAll<'t y p e s', ' ', ''>; // expected to be 'types' | |
| // type replaced2 = ReplaceAll<'types', 's', 'e'>; // expected to be 'types' | |
| // type replaced3 = ReplaceAll<'test', 't', 'f'>; // expected to be 'types' | |
| // type LengthOfString<S extends string, L extends string[] = []> = S extends `${any}${infer R}` | |
| // ? LengthOfString<R, [...L, string]> | |
| // : L['length'] | |
| // type a = LengthOfString<'giorgi'>; | |
| // type Trim<T extends string> = T extends `${infer F}${infer R}${infer E}` | |
| // ? F extends ' ' | |
| // ? `${Trim<R>}${Trim<E>}` : `${F}${R}${Trim<E>}` | |
| // : T; | |
| // type Space = ' ' | '\n' | '\t' | |
| // type Trim<S extends string> = S extends `${Space}${infer R}${Space}` | `${Space}${infer R}` | `${infer R}${Space}` ? Trim<R> : S | |
| // type trimmed = Trim<' Hello World '> // expected to be 'Hello World' | |
| // type Reverse<T extends unknown[] = []> = T extends [...infer R, infer L] ? [L, ...Reverse<R>] : T; | |
| // type a = Reverse<['a', 'b']> // ['b', 'a'] | |
| // type b = Reverse<['a', 'b', 'c']> // ['c', 'b', 'a'] | |
| // type Shift<T extends unknown[]> = T extends [infer F, ...infer R] ? R : T; | |
| // type Result = Shift<[3, 2, 1]> // [2, 1] | |
| // @TODO | |
| // type Without<T extends unknown[], E> = T extends [infer F, ... infer R] ? | |
| // F extends keyof E | E ? Without<R, E> : [F, ...Without<R, E>] | |
| // : T; | |
| // type Res = Without<[1, 2], 1>; // expected to be [2] | |
| // type Res1 = Without<[1, 2, 4, 1, 5], [1, 2]>; // expected to be [4, 5] | |
| // type Res2 = Without<[2, 3, 2, 3, 2, 3, 2, 3], [2, 3]>; // expected to be [] | |
| // type Check = 1 extends keyof [1, 2] ? true : false; | |
| // type StartsWith<T extends string, S extends string> = T extends `${S}${infer R}` ? true : false; | |
| // type a = StartsWith<'abc', 'ac'> // expected to be false | |
| // type b = StartsWith<'abc', 'ab'> // expected to be true | |
| // type c = StartsWith<'abc', 'abcd'> // expected to be false | |
| // type CamelCase<S extends string> = S extends `${infer F}${infer R}` ? F extends '_' ? `${Capitalize<CamelCase<R>>}` : `${F}${CamelCase<R>}` : S ; | |
| // type camelCase1 = CamelCase<'hello_world_with_types'> // expected to be 'helloWorldWithTypes' | |
| // type camelCase2 = CamelCase<'HELLO_WORLD_WITH_TYPES'> // expected to be same as previous one | |
| // type KebabCase<S extends string> = S extends `${infer F}${infer R}` ? F extends Uppercase<F> ? `-${Lowercase<F>}${KebabCase<R>}` : `${F}${KebabCase<R>}` : S ; | |
| // type kebabCase1 = KebabCase<'helloWorldWithTypes'> // expected to be 'hello-world-with-types' | |
| // type kebabCase2 = KebabCase<'somethingStrange'> // expected to 'something-strange' | |
| type Zip<T extends unknown[], U extends unknown[]> = ; | |
| type exp = Zip<[1, 2], [true, false]> // expected to be [[1, true], [2, false]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment