-
Notifications
You must be signed in to change notification settings - Fork 2
/
problems.json
1 lines (1 loc) · 232 KB
/
problems.json
1
[{"no":2,"difficulty":"medium","path":"00002-medium-return-type","info":{"zh-CN":{"title":"获取函数返回类型"},"en":{"title":"Get Return Type","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["infer","built-in"],"tsconfig":null,"original_issues":null,"recommended_solutions":null}},"readme":{"zh-CN":"不使用 `ReturnType` 实现 TypeScript 的 `ReturnType<T>` 泛型。\n\n例如:\n\n```ts\nconst fn = (v: boolean) => {\n if (v)\n return 1\n else\n return 2\n}\n\ntype a = MyReturnType<typeof fn> // 应推导出 \"1 | 2\"\n```","ja":"組み込みの型ユーティリティ`ReturnType<T>`を使用せず、`T`の戻り値の型を取得する型を実装します。\n\n例えば\n\n```ts\nconst fn = (v: boolean) => {\n if (v)\n return 1\n else\n return 2\n}\n\ntype a = MyReturnType<typeof fn> // should be \"1 | 2\"\n```","ko":"내장 제네릭 `ReturnType<T>`을 이를 사용하지 않고 구현하세요.\n\n예시:\n\n```ts\nconst fn = (v: boolean) => {\n if (v)\n return 1\n else\n return 2\n}\n\ntype a = MyReturnType<typeof fn> // should be \"1 | 2\"\n```","en":"Implement the built-in `ReturnType<T>` generic without using it.\n\nFor example\n\n```ts\nconst fn = (v: boolean) => {\n if (v)\n return 1\n else\n return 2\n}\n\ntype a = MyReturnType<typeof fn> // should be \"1 | 2\"\n```"},"template":"type MyReturnType<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<string, MyReturnType<() => string>>>,\n Expect<Equal<123, MyReturnType<() => 123>>>,\n Expect<Equal<ComplexObject, MyReturnType<() => ComplexObject>>>,\n Expect<Equal<Promise<boolean>, MyReturnType<() => Promise<boolean>>>>,\n Expect<Equal<() => 'foo', MyReturnType<() => () => 'foo'>>>,\n Expect<Equal<1 | 2, MyReturnType<typeof fn>>>,\n Expect<Equal<1 | 2, MyReturnType<typeof fn1>>>,\n]\n\ntype ComplexObject = {\n a: [12, 'foo']\n bar: 'hello'\n prev(): number\n}\n\nconst fn = (v: boolean) => v ? 1 : 2\nconst fn1 = (v: boolean, w: any) => v ? 1 : 2\n"},{"no":3,"difficulty":"medium","path":"00003-medium-omit","info":{"zh-CN":{"title":"实现 Omit"},"en":{"title":"Omit","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["union","built-in"],"related":["4"]}},"readme":{"zh-CN":"不使用 `Omit` 实现 TypeScript 的 `Omit<T, K>` 泛型。\n\n`Omit` 会创建一个省略 `K` 中字段的 `T` 对象。\n\n例如:\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ntype TodoPreview = MyOmit<Todo, 'description' | 'title'>\n\nconst todo: TodoPreview = {\n completed: false,\n}\n```","ja":"組み込みの型ユーティリティ`Omit<T, K>`を使用せず、`T`のプロパティから`K`を削除する型を実装します。\n\n例えば\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ntype TodoPreview = MyOmit<Todo, 'description' | 'title'>\n\nconst todo: TodoPreview = {\n completed: false,\n}\n```","ko":"`T`에서 `K` 프로퍼티만 제거해 새로운 오브젝트 타입을 만드는 내장 제네릭 `Omit<T, K>`를 이를 사용하지 않고 구현하세요.\n\n예시:\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ntype TodoPreview = MyOmit<Todo, 'description' | 'title'>\n\nconst todo: TodoPreview = {\n completed: false,\n}\n```","en":"Implement the built-in `Omit<T, K>` generic without using it.\n\nConstructs a type by picking all properties from `T` and then removing `K`\n\nFor example\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ntype TodoPreview = MyOmit<Todo, 'description' | 'title'>\n\nconst todo: TodoPreview = {\n completed: false,\n}\n```"},"template":"type MyOmit<T, K> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Expected1, MyOmit<Todo, 'description'>>>,\n Expect<Equal<Expected2, MyOmit<Todo, 'description' | 'completed'>>>,\n]\n\n// @ts-expect-error\ntype error = MyOmit<Todo, 'description' | 'invalid'>\n\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ninterface Expected1 {\n title: string\n completed: boolean\n}\n\ninterface Expected2 {\n title: string\n}\n"},{"no":4,"difficulty":"easy","path":"00004-easy-pick","info":{"zh-CN":{"title":"实现 Pick"},"en":{"title":"Pick","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["union","built-in"],"related":["3"]}},"readme":{"zh-CN":"> 欢迎 PR 改进翻译质量。\n\n实现 TS 内置的 `Pick<T, K>`,但不可以使用它。\n\n**从类型 `T` 中选择出属性 `K`,构造成一个新的类型**。\n\n例如:\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ntype TodoPreview = MyPick<Todo, 'title' | 'completed'>\n\nconst todo: TodoPreview = {\n title: 'Clean room',\n completed: false,\n}\n```","ja":"組み込みの型ユーティリティ`Pick<T, K>`を使用せず、`T`から`K`のプロパティを抽出する型を実装します。\n\n例えば\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ntype TodoPreview = MyPick<Todo, 'title' | 'completed'>\n\nconst todo: TodoPreview = {\n title: 'Clean room',\n completed: false,\n}\n```","ko":"`T`에서 `K` 프로퍼티만 선택해 새로운 오브젝트 타입을 만드는 내장 제네릭 `Pick<T, K>`을 이를 사용하지 않고 구현하세요.\n\n예시:\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ntype TodoPreview = MyPick<Todo, 'title' | 'completed'>\n\nconst todo: TodoPreview = {\n title: 'Clean room',\n completed: false,\n}\n```","en":"Implement the built-in `Pick<T, K>` generic without using it.\n\nConstructs a type by picking the set of properties `K` from `T`\n\nFor example\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ntype TodoPreview = MyPick<Todo, 'title' | 'completed'>\n\nconst todo: TodoPreview = {\n title: 'Clean room',\n completed: false,\n}\n```"},"template":"type MyPick<T, K> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Expected1, MyPick<Todo, 'title'>>>,\n Expect<Equal<Expected2, MyPick<Todo, 'title' | 'completed'>>>,\n // @ts-expect-error\n MyPick<Todo, 'title' | 'completed' | 'invalid'>,\n]\n\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\ninterface Expected1 {\n title: string\n}\n\ninterface Expected2 {\n title: string\n completed: boolean\n}\n"},{"no":5,"difficulty":"extreme","path":"00005-extreme-readonly-keys","info":{"zh-CN":{"title":"获取只读字段"},"en":{"title":"Get Readonly Keys","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["utils","object-keys"]}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n实现泛型`GetReadonlyKeys<T>`,该`GetReadonlyKeys<T>`返回对象的只读键的并集。\n\n例如\n\n```ts\ninterface Todo {\n readonly title: string\n readonly description: string\n completed: boolean\n}\n\ntype Keys = GetReadonlyKeys<Todo> // expected to be \"title\" | \"description\"\n```","ja":"オブジェクトの読み取り専用キーの Union を返す汎用的な `GetReadonlyKeys<T>` を実装してください。\n\n例えば\n\n```ts\ninterface Todo {\n readonly title: string\n readonly description: string\n completed: boolean\n}\n\ntype Keys = GetReadonlyKeys<Todo> // expected to be \"title\" | \"description\"\n```","en":"Implement a generic `GetReadonlyKeys<T>` that returns a union of the readonly keys of an Object.\n\nFor example\n\n```ts\ninterface Todo {\n readonly title: string\n readonly description: string\n completed: boolean\n}\n\ntype Keys = GetReadonlyKeys<Todo> // expected to be \"title\" | \"description\"\n```"},"template":"type GetReadonlyKeys<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<'title', GetReadonlyKeys<Todo1>>>,\n Expect<Equal<'title' | 'description', GetReadonlyKeys<Todo2>>>,\n]\n\ninterface Todo1 {\n readonly title: string\n description: string\n completed: boolean\n}\n\ninterface Todo2 {\n readonly title: string\n readonly description: string\n completed?: boolean\n}\n"},{"no":6,"difficulty":"hard","path":"00006-hard-simple-vue","info":{"zh-CN":{"title":"简单的 Vue 类型"},"en":{"title":"Simple Vue","author":{"name":"Anthony Fu","github":"antfu"},"tags":["this","application","vue"],"related":["213"]}},"readme":{"zh-CN":"实现类似Vue的类型支持的简化版本。\n\n通过提供一个函数`SimpleVue`(类似于`Vue.extend`或`defineComponent`),它应该正确地推断出 computed 和 methods 内部的`this`类型。\n\n在此挑战中,我们假设`SimpleVue`接受只带有`data`,`computed`和`methods`字段的Object作为其唯一的参数,\n\n-`data`是一个简单的函数,它返回一个提供上下文`this`的对象,但是你无法在`data`中获取其他的计算属性或方法。\n\n-`computed`是将`this`作为上下文的函数的对象,进行一些计算并返回结果。在上下文中应暴露计算出的值而不是函数。\n\n-`methods`是函数的对象,其上下文也为`this`。函数中可以访问`data`,`computed`以及其他`methods`中的暴露的字段。 `computed`与`methods`的不同之处在于`methods`在上下文中按原样暴露为函数。\n\n`SimpleVue`的返回值类型可以是任意的。\n\n```ts\nconst instance = SimpleVue({\n data() {\n return {\n firstname: 'Type',\n lastname: 'Challenges',\n amount: 10,\n }\n },\n computed: {\n fullname() {\n return this.firstname + ' ' + this.lastname\n }\n },\n methods: {\n hi() {\n alert(this.fullname.toLowerCase())\n }\n }\n})\n```","ja":"Vue ライクな型付けの簡略化されたバージョンを実装してください。\n\n関数名 `SimpleVue` (`Vue.extend` や `defineComponent` のようなもの) を与えることで、computed や methods の中の `this` 型を適切に推論できます。\n\nこの課題では、SimpleVue が `data`、 `computed`、 `methods` フィールドを持つオブジェクトを唯一の引数として受け取れることにします。\n\n- `data` はコンテキスト `this` を公開するオブジェクトを返す単純な関数ですが、自身や算出プロパティ、メソッドにアクセスできません。\n\n- `computed` は、コンテキストを `this` として受け取り何らかの計算をし、その結果を返す関数のオブジェクトです。計算された結果は、関数ではなくプレーンな戻り値としてコンテキストに公開されなければなりません。\n\n- `methods` は同様に `this` をコンテキストとする関数のオブジェクトです。メソッドは他の `methods` と同様に `data`、 `computed`、 `methods` で公開されているフィールドにアクセスできます。`computed` と異なるのは、`method` がそのまま関数として公開されている点です。\n\n`SimpleVue` の戻り値の型は任意です。\n\n```ts\nconst instance = SimpleVue({\n data() {\n return {\n firstname: 'Type',\n lastname: 'Challenges',\n amount: 10,\n }\n },\n computed: {\n fullname() {\n return this.firstname + ' ' + this.lastname\n }\n },\n methods: {\n hi() {\n alert(this.fullname.toLowerCase())\n }\n }\n})\n```","en":"Implement a simpiled version of a Vue-like typing support.\n\nBy providing a function name `SimpleVue` (similar to `Vue.extend` or `defineComponent`), it should properly infer the `this` type inside computed and methods.\n\nIn this challenge, we assume that SimpleVue take an Object with `data`, `computed` and `methods` fields as it's only argument,\n\n- `data` is a simple function that returns an object that exposes the context `this`, but you won't be accessible to other computed values or methods.\n\n- `computed` is an Object of functions that take the context as `this`, doing some calculation and returns the result. The computed results should be exposed to the context as the plain return values instead of functions.\n\n- `methods` is an Object of functions that take the context as `this` as well. Methods can access the fields exposed by `data`, `computed` as well as other `methods`. The different between `computed` is that `methods` exposed as functions as-is.\n\nThe type of `SimpleVue`'s return value can be arbitrary.\n\n```ts\nconst instance = SimpleVue({\n data() {\n return {\n firstname: 'Type',\n lastname: 'Challenges',\n amount: 10,\n }\n },\n computed: {\n fullname() {\n return this.firstname + ' ' + this.lastname\n }\n },\n methods: {\n hi() {\n alert(this.fullname.toLowerCase())\n }\n }\n})\n```"},"template":"declare function SimpleVue(options: any): any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nSimpleVue({\n data() {\n // @ts-expect-error\n this.firstname\n // @ts-expect-error\n this.getRandom()\n // @ts-expect-error\n this.data()\n\n return {\n firstname: 'Type',\n lastname: 'Challenges',\n amount: 10,\n }\n },\n computed: {\n fullname() {\n return `${this.firstname} ${this.lastname}`\n },\n },\n methods: {\n getRandom() {\n return Math.random()\n },\n hi() {\n alert(this.amount)\n alert(this.fullname.toLowerCase())\n alert(this.getRandom())\n },\n test() {\n const fullname = this.fullname\n const cases: [Expect<Equal<typeof fullname, string>>] = [] as any\n },\n },\n})\n"},{"no":7,"difficulty":"easy","path":"00007-easy-readonly","info":{"zh-CN":{"title":"实现 Readonly"},"en":{"title":"Readonly","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["built-in","readonly","object-keys"],"related":["8","9"]}},"readme":{"zh-CN":"> 欢迎 PR 改进翻译质量。\n\n不要使用内置的`Readonly<T>`,自己实现一个。\n\n该 `Readonly` 会接收一个 _泛型参数_,并返回一个完全一样的类型,只是所有属性都会被 `readonly` 所修饰。\n\n也就是不可以再对该对象的属性赋值。\n\n例如:\n\n```ts\ninterface Todo {\n title: string\n description: string\n}\n\nconst todo: MyReadonly<Todo> = {\n title: \"Hey\",\n description: \"foobar\"\n}\n\ntodo.title = \"Hello\" // Error: cannot reassign a readonly property\ntodo.description = \"barFoo\" // Error: cannot reassign a readonly property\n```","ja":"組み込みの型ユーティリティ`Readonly<T>`を使用せず、`T` のすべてのプロパティを読み取り専用にする型を実装します。実装された型のプロパティは再割り当てできません。\n\n例えば\n\n```ts\ninterface Todo {\n title: string\n description: string\n}\n\nconst todo: MyReadonly<Todo> = {\n title: \"Hey\",\n description: \"foobar\"\n}\n\ntodo.title = \"Hello\" // Error: cannot reassign a readonly property\ntodo.description = \"barFoo\" // Error: cannot reassign a readonly property\n```","ko":"`T`의 모든 프로퍼티를 읽기 전용(재할당 불가)으로 바꾸는 내장 제네릭 `Readonly<T>`를 이를 사용하지 않고 구현하세요.\n\n예시:\n\n```ts\ninterface Todo {\n title: string\n description: string\n}\n\nconst todo: MyReadonly<Todo> = {\n title: \"Hey\",\n description: \"foobar\"\n}\n\ntodo.title = \"Hello\" // Error: cannot reassign a readonly property\ntodo.description = \"barFoo\" // Error: cannot reassign a readonly property\n```","en":"Implement the built-in `Readonly<T>` generic without using it.\n\nConstructs a type with all properties of T set to readonly, meaning the properties of the constructed type cannot be reassigned.\n\nFor example\n\n```ts\ninterface Todo {\n title: string\n description: string\n}\n\nconst todo: MyReadonly<Todo> = {\n title: \"Hey\",\n description: \"foobar\"\n}\n\ntodo.title = \"Hello\" // Error: cannot reassign a readonly property\ntodo.description = \"barFoo\" // Error: cannot reassign a readonly property\n```"},"template":"type MyReadonly<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<MyReadonly<Todo1>, Readonly<Todo1>>>,\n]\n\ninterface Todo1 {\n title: string\n description: string\n completed: boolean\n meta: {\n author: string\n }\n}\n"},{"no":8,"difficulty":"medium","path":"00008-medium-readonly-2","info":{"zh-CN":{"title":"Readonly 2"},"en":{"title":"Readonly 2","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["readonly","object-keys"],"related":["7","9"]}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n实现一个通用`MyReadonly2<T, K>`,它带有两种类型的参数`T`和`K`。\n\n`K`指定应设置为Readonly的`T`的属性集。如果未提供`K`,则应使所有属性都变为只读,就像普通的`Readonly<T>`一样。\n\n例如\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\nconst todo: MyReadonly2<Todo, 'title' | 'description'> = {\n title: \"Hey\",\n description: \"foobar\",\n completed: false,\n}\n\ntodo.title = \"Hello\" // Error: cannot reassign a readonly property\ntodo.description = \"barFoo\" // Error: cannot reassign a readonly property\ntodo.completed = true // OK\n```","ja":"2つの型引数`T`と`K`を取る`MyReadonly2<T, K>`を実装します。\n\n`K`が指定されている場合は、`T`の中の`K`のプロパティのみを読み取り専用にします。`K`が指定されていない場合は、通常の`Readonly<T>`と同様に、すべてのプロパティを読み取り専用にします。\n\n例えば\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\nconst todo: MyReadonly2<Todo, 'title' | 'description'> = {\n title: \"Hey\",\n description: \"foobar\",\n completed: false,\n}\n\ntodo.title = \"Hello\" // Error: cannot reassign a readonly property\ntodo.description = \"barFoo\" // Error: cannot reassign a readonly property\ntodo.completed = true // OK\n```","ko":"`T`에서 `K` 프로퍼티만 읽기 전용으로 설정해 새로운 오브젝트 타입을 만드는 제네릭 `MyReadonly2<T, K>`를 구현하세요. `K`가 주어지지 않으면 단순히 `Readonly<T>`처럼 모든 프로퍼티를 읽기 전용으로 설정해야 합니다.\n\n예시:\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\nconst todo: MyReadonly2<Todo, 'title' | 'description'> = {\n title: \"Hey\",\n description: \"foobar\",\n completed: false,\n}\n\ntodo.title = \"Hello\" // Error: cannot reassign a readonly property\ntodo.description = \"barFoo\" // Error: cannot reassign a readonly property\ntodo.completed = true // OK\n```","en":"Implement a generic `MyReadonly2<T, K>` which takes two type argument `T` and `K`.\n\n`K` specify the set of properties of `T` that should set to Readonly. When `K` is not provided, it should make all properties readonly just like the normal `Readonly<T>`.\n\nFor example\n\n```ts\ninterface Todo {\n title: string\n description: string\n completed: boolean\n}\n\nconst todo: MyReadonly2<Todo, 'title' | 'description'> = {\n title: \"Hey\",\n description: \"foobar\",\n completed: false,\n}\n\ntodo.title = \"Hello\" // Error: cannot reassign a readonly property\ntodo.description = \"barFoo\" // Error: cannot reassign a readonly property\ntodo.completed = true // OK\n```"},"template":"type MyReadonly2<T, K> = any\n","tests":"import type { Alike, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Alike<MyReadonly2<Todo1>, Readonly<Todo1>>>,\n Expect<Alike<MyReadonly2<Todo1, 'title' | 'description'>, Expected>>,\n Expect<Alike<MyReadonly2<Todo2, 'title' | 'description'>, Expected>>,\n]\n\ninterface Todo1 {\n title: string\n description?: string\n completed: boolean\n}\n\ninterface Todo2 {\n readonly title: string\n description?: string\n completed: boolean\n}\n\ninterface Expected {\n readonly title: string\n readonly description?: string\n completed: boolean\n}\n"},{"no":9,"difficulty":"medium","path":"00009-medium-deep-readonly","info":{"zh-CN":{"title":"深度 Readonly"},"en":{"title":"Deep Readonly","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["readonly","object-keys","deep"],"related":["7","8"]}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n实现一个通用的`DeepReadonly<T>`,它将对象的每个参数及其子对象递归地设为只读。\n\n您可以假设在此挑战中我们仅处理对象。数组,函数,类等都无需考虑。但是,您仍然可以通过覆盖尽可能多的不同案例来挑战自己。\n\n例如\n\n```ts\ntype X = { \n x: { \n a: 1\n b: 'hi'\n }\n y: 'hey'\n}\n\ntype Expected = { \n readonly x: { \n readonly a: 1\n readonly b: 'hi'\n }\n readonly y: 'hey' \n}\n\ntype Todo = DeepReadonly<X> // should be same as `Expected`\n```","ja":"オブジェクトのすべてのパラメーター(およびそのサブオブジェクトを再帰的に)を読み取り専用にする`DeepReadonly<T>`を実装します。\n\nこの課題ではオブジェクトのみを扱っていると想定してください。配列、関数、クラスなどは考慮する必要はありません。しかし、可能な限り様々なケースをカバーすることで、自分自身に挑戦することができます。\n\n例えば\n\n```ts\ntype X = { \n x: { \n a: 1\n b: 'hi'\n }\n y: 'hey'\n}\n\ntype Expected = { \n readonly x: { \n readonly a: 1\n readonly b: 'hi'\n }\n readonly y: 'hey' \n}\n\ntype Todo = DeepReadonly<X> // should be same as `Expected`\n```","ko":"객체의 프로퍼티와 모든 하위 객체를 재귀적으로 읽기 전용으로 설정하는 제네릭 `DeepReadonly<T>`를 구현하세요.\n\n이 챌린지에서는 타입 파라미터 `T`를 객체 타입으로 제한하고 있습니다. 객체뿐만 아니라 배열, 함수, 클래스 등 가능한 다양한 형태의 타입 파라미터를 사용하도록 도전해 보세요.\n\n예시:\n\n```ts\ntype X = { \n x: { \n a: 1\n b: 'hi'\n }\n y: 'hey'\n}\n\ntype Expected = { \n readonly x: { \n readonly a: 1\n readonly b: 'hi'\n }\n readonly y: 'hey' \n}\n\ntype Todo = DeepReadonly<X> // should be same as `Expected`\n```","en":"Implement a generic `DeepReadonly<T>` which make every parameter of an object - and its sub-objects recursively - readonly.\n\nYou can assume that we are only dealing with Objects in this challenge. Arrays, Functions, Classes and so on are no need to take into consideration. However, you can still challenge your self by covering different cases as many as possible.\n\nFor example\n\n```ts\ntype X = { \n x: { \n a: 1\n b: 'hi'\n }\n y: 'hey'\n}\n\ntype Expected = { \n readonly x: { \n readonly a: 1\n readonly b: 'hi'\n }\n readonly y: 'hey' \n}\n\ntype Todo = DeepReadonly<X> // should be same as `Expected`\n```"},"template":"type DeepReadonly<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<DeepReadonly<X>, Expected>>,\n]\n\ntype X = {\n a: () => 22\n b: string\n c: {\n d: boolean\n e: {\n g: {\n h: {\n i: true\n j: 'string'\n }\n k: 'hello'\n }\n l: [\n 'hi',\n {\n m: ['hey']\n },\n ]\n }\n }\n}\n\ntype Expected = {\n readonly a: () => 22\n readonly b: string\n readonly c: {\n readonly d: boolean\n readonly e: {\n readonly g: {\n readonly h: {\n readonly i: true\n readonly j: 'string'\n }\n readonly k: 'hello'\n }\n readonly l: readonly [\n 'hi',\n {\n readonly m: readonly ['hey']\n },\n ]\n }\n }\n}\n"},{"no":10,"difficulty":"medium","path":"00010-medium-tuple-to-union","info":{"zh-CN":{"title":"元组转合集"},"en":{"title":"Tuple to Union","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["infer","tuple","union"],"related":["11","472","730","3188"]}},"readme":{"zh-CN":"实现泛型`TupleToUnion<T>`,它返回元组所有值的合集。\n\n例如\n\n```ts\ntype Arr = ['1', '2', '3']\n\ntype Test = TupleToUnion<Arr> // expected to be '1' | '2' | '3'\n```","ja":"タプルの値からユニオン型を生成する`TupleToUnion<T>`を実装します。\n\n例えば\n\n```ts\ntype Arr = ['1', '2', '3']\n\ntype Test = TupleToUnion<Arr> // expected to be '1' | '2' | '3'\n```","ko":"튜플 값으로 유니온 타입을 생성하는 제네릭 `TupleToUnion<T>`를 구현하세요.\n\n예시:\n\n```ts\ntype Arr = ['1', '2', '3']\n\ntype Test = TupleToUnion<Arr> // expected to be '1' | '2' | '3'\n```","en":"Implement a generic `TupleToUnion<T>` which covers the values of a tuple to its values union.\n\nFor example\n\n```ts\ntype Arr = ['1', '2', '3']\n\ntype Test = TupleToUnion<Arr> // expected to be '1' | '2' | '3'\n```"},"template":"type TupleToUnion<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<TupleToUnion<[123, '456', true]>, 123 | '456' | true>>,\n Expect<Equal<TupleToUnion<[123]>, 123>>,\n]\n"},{"no":11,"difficulty":"easy","path":"00011-easy-tuple-to-object","info":{"zh-CN":{"title":"元组转换为对象"},"en":{"title":"Tuple to Object","author":{"name":"sinoon","email":"[email protected]","github":"sinoon"},"related":["10","472","730","3188"]}},"readme":{"zh-CN":"> 欢迎 PR 改进翻译质量。\n\n传入一个元组类型,将这个元组类型转换为对象类型,这个对象类型的键/值都是从元组中遍历出来。\n\n例如:\n\n```ts\nconst tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const\n\ntype result = TupleToObject<typeof tuple> // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}\n```","ja":"タプルを受け取り、その各値のkey/valueを持つオブジェクトの型に変換する型を実装します。\n\n例えば\n\n```ts\nconst tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const\n\ntype result = TupleToObject<typeof tuple> // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}\n```","ko":"배열(튜플)을 받아, 각 원소의 값을 key/value로 갖는 오브젝트 타입을 반환하는 타입을 구현하세요.\n\n예시:\n\n```ts\nconst tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const\n\ntype result = TupleToObject<typeof tuple> // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}\n```","en":"Give an array, transform into an object type and the key/value must in the given array.\n\nFor example\n\n```ts\nconst tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const\n\ntype result = TupleToObject<typeof tuple> // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}\n```"},"template":"type TupleToObject<T extends readonly any[]> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nconst tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const\n\ntype cases = [\n Expect<Equal<TupleToObject<typeof tuple>, { tesla: 'tesla'; 'model 3': 'model 3'; 'model X': 'model X'; 'model Y': 'model Y' }>>,\n]\n\n// @ts-expect-error\ntype error = TupleToObject<[[1, 2], {}]>\n"},{"no":12,"difficulty":"medium","path":"00012-medium-chainable-options","info":{"zh-CN":{"title":"可串联构造器"},"en":{"title":"Chainable Options","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["application"]}},"readme":{"zh-CN":"在 JavaScript 中我们很常会使用可串联(Chainable/Pipeline)的函数构造一个对象,但在 TypeScript 中,你能合理的给他附上类型吗?\n\n在这个挑战中,你可以使用任意你喜欢的方式实现这个类型 - Interface, Type 或 Class 都行。你需要提供两个函数 `option(key, value)` 和 `get()`。在 `option` 中你需要使用提供的 key 和 value 扩展当前的对象类型,通过 `get` 获取最终结果。\n\n例如\n\n```ts\ndeclare const config: Chainable\n\nconst result = config\n .option('foo', 123)\n .option('name', 'type-challenges')\n .option('bar', { value: 'Hello World' })\n .get()\n\n// 期望 result 的类型是:\ninterface Result {\n foo: number\n name: string\n bar: {\n value: string\n }\n}\n```\n\n你只需要在类型层面实现这个功能 - 不需要实现任何 TS/JS 的实际逻辑。\n\n你可以假设 `key` 只接受字符串而 `value` 接受任何类型,你只需要暴露它传递的类型而不需要进行任何处理。同样的 `key` 只会被使用一次。","ja":"JavaScript では、チェイン可能なオプションがよく使われます。しかし、TypeScript に切り替えたとき、正しく型を付けることができますか?\n\nこの課題では、オブジェクトでもクラスでも何でもいいので、 `option(key, value)` と `get()` の 2 つの関数を提供する型を定義してください。`option` では、与えられたキーと値を使って現在の config の型を拡張できます。最終的な結果は `get` で取得することにしましょう。\n\n例えば\n\n```ts\ndeclare const config: Chainable\n\nconst result = config\n .option('foo', 123)\n .option('name', 'type-challenges')\n .option('bar', { value: 'Hello World' })\n .get()\n\n// expect the type of result to be:\ninterface Result {\n foo: number\n name: string\n bar: {\n value: string\n }\n}\n```\n\nこの問題を解くために js/ts のロジックを書く必要はありません。型レベルのロジックだけを書いてください。\n\n`key` は `string` のみを受け付け、`value` は任意の型を受け付けると仮定しても構いません。同じ `key` が 2 回渡されることはありません。","en":"Chainable options are commonly used in Javascript. But when we switch to TypeScript, can you properly type it?\n\nIn this challenge, you need to type an object or a class - whatever you like - to provide two function `option(key, value)` and `get()`. In `option`, you can extend the current config type by the given key and value. We should about to access the final result via `get`.\n\nFor example\n\n```ts\ndeclare const config: Chainable\n\nconst result = config\n .option('foo', 123)\n .option('name', 'type-challenges')\n .option('bar', { value: 'Hello World' })\n .get()\n\n// expect the type of result to be:\ninterface Result {\n foo: number\n name: string\n bar: {\n value: string\n }\n}\n```\n\nYou don't need to write any js/ts logic to handle the problem - just in type level. \n\nYou can assume that `key` only accepts `string` and the `value` can be anything - just leave it as-is. Same `key` won't be passed twice."},"template":"type Chainable = {\n option(key: string, value: any): any\n get(): any\n}\n","tests":"import type { Alike, Expect } from '@type-challenges/utils'\n\ndeclare const a: Chainable\n\nconst result1 = a\n .option('foo', 123)\n .option('bar', { value: 'Hello World' })\n .option('name', 'type-challenges')\n .get()\n\nconst result2 = a\n .option('name', 'another name')\n // @ts-expect-error\n .option('name', 'last name')\n .get()\n\ntype cases = [\n Expect<Alike<typeof result1, Expected1>>,\n Expect<Alike<typeof result2, Expected2>>,\n]\n\ntype Expected1 = {\n foo: number\n bar: {\n value: string\n }\n name: string\n}\n\ntype Expected2 = {\n name: string\n}\n"},{"no":13,"difficulty":"warm","path":"00013-warm-hello-world","info":{"en":{"title":"Hello World","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"}}},"readme":{"zh-CN":"Hello, World!\n\n这个简单的提问希望让你可以快速上手 Type Challenges。在这里,我们使用了一些神奇的技巧让 TypeScript 通过自身的类型系统来实现自动判题。\n\n在这个挑战中,你需要修改下方的代码使得测试通过(使其没有类型错误)。\n\n```ts\n// 期望是一个 string 类型\ntype HelloWorld = any\n```\n\n```ts\n// 你需要使得如下这行不会抛出异常\ntype test = Expect<Equal<HelloWorld, string>>\n```\n\n点击上方的 `接受挑战` 开始编码!旅途愉快!","ja":"Hello, World!\n\nType Challenges では、型システム自体を使用してアサーションを実行します。\n\nこの課題では、次のコードを変更してテストに合格する必要があります(型チェックエラーなし)。\n\n```ts\n// expected to be string\ntype HelloWorld = any\n```\n\n```ts\n// you should make this work\ntype test = Expect<Equal<HelloWorld, string>>\n```\n\n「挑戦する」ボタンをクリックしてコーディングを開始してください! Happy Hacking!","ko":"Hello, World!\n\nType Challenges에서는 타입 단언(assertion)을 하기 위해 자체적인 타입 시스템을 사용합니다.\n\n이 과제에서는, 아래의 코드를 변경해서 테스트 코드를 통과하세요. (타입 체크 에러 없음).\n\n```ts\n// string이 되어야 합니다.\ntype HelloWorld = any\n```\n\n```ts\n// 아래의 테스트가 통과하도록 만드세요.\ntype test = Expect<Equal<HelloWorld, string>>\n```\n\n`Take the Challenge` 버튼을 클릭해서 코딩을 시작하세요! Happy Hacking!","en":"Hello, World!\n\nIn Type Challenges, we use the type system itself to do the assertion.\n\nFor this challenge, you will need to change the following code to make the tests pass (no type check errors).\n\n```ts\n// expected to be string\ntype HelloWorld = any\n```\n\n```ts\n// you should make this work\ntype test = Expect<Equal<HelloWorld, string>>\n```\n\nClick the `Take the Challenge` button to start coding! Happy Hacking!"},"template":"type HelloWorld = any // expected to be a string\n","tests":"import type { Equal, Expect, NotAny } from '@type-challenges/utils'\n\ntype cases = [\n Expect<NotAny<HelloWorld>>,\n Expect<Equal<HelloWorld, string>>,\n]\n"},{"no":14,"difficulty":"easy","path":"00014-easy-first","info":{"zh-CN":{"title":"第一个元素"},"en":{"title":"First of Array","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["array"],"related":["15"]}},"readme":{"zh-CN":"> 欢迎 PR 改进翻译质量。\n\n实现一个通用`First<T>`,它接受一个数组`T`并返回它的第一个元素的类型。\n\n例如:\n\n```ts\ntype arr1 = ['a', 'b', 'c']\ntype arr2 = [3, 2, 1]\n\ntype head1 = First<arr1> // expected to be 'a'\ntype head2 = First<arr2> // expected to be 3\n```","ja":"配列`T`を受け取り、その最初のプロパティの型を返す`First<T>`を実装します。\n\n例えば\n\n```ts\ntype arr1 = ['a', 'b', 'c']\ntype arr2 = [3, 2, 1]\n\ntype head1 = First<arr1> // expected to be 'a'\ntype head2 = First<arr2> // expected to be 3\n```","ko":"배열(튜플) `T`를 받아 첫 원소의 타입을 반환하는 제네릭 `First<T>`를 구현하세요.\n\n예시:\n\n```ts\ntype arr1 = ['a', 'b', 'c']\ntype arr2 = [3, 2, 1]\n\ntype head1 = First<arr1> // expected to be 'a'\ntype head2 = First<arr2> // expected to be 3\n```","en":"Implement a generic `First<T>` that takes an Array `T` and returns it's first element's type.\n\nFor example\n\n```ts\ntype arr1 = ['a', 'b', 'c']\ntype arr2 = [3, 2, 1]\n\ntype head1 = First<arr1> // expected to be 'a'\ntype head2 = First<arr2> // expected to be 3\n```"},"template":"type First<T extends any[]> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<First<[3, 2, 1]>, 3>>,\n Expect<Equal<First<[() => 123, { a: string }]>, () => 123>>,\n Expect<Equal<First<[]>, never>>,\n Expect<Equal<First<[undefined]>, undefined>>,\n]\n\ntype errors = [\n // @ts-expect-error\n First<'notArray'>,\n // @ts-expect-error\n First<{ 0: 'arrayLike' }>,\n]\n"},{"no":15,"difficulty":"medium","path":"00015-medium-last","info":{"zh-CN":{"title":"最后一个元素"},"en":{"title":"Last of Array","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["array"],"related":["14","16"]}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n>在此挑战中建议使用TypeScript 4.0\n\n实现一个通用`Last<T>`,它接受一个数组`T`并返回其最后一个元素的类型。\n\n例如\n\n```ts\ntype arr1 = ['a', 'b', 'c']\ntype arr2 = [3, 2, 1]\n\ntype tail1 = Last<arr1> // expected to be 'c'\ntype tail2 = Last<arr2> // expected to be 1\n```","ja":"> この課題ではTypeScript 4.0が推奨されます\n\n配列 `T` を受け取り、その最後の要素の型を返す汎用的な `Last<T>` を実装してください。\n\n例えば\n\n```ts\ntype arr1 = ['a', 'b', 'c']\ntype arr2 = [3, 2, 1]\n\ntype tail1 = Last<arr1> // expected to be 'c'\ntype tail2 = Last<arr2> // expected to be 1\n```","en":"> TypeScript 4.0 is recommended in this challenge\n\nImplement a generic `Last<T>` that takes an Array `T` and returns its last element.\n\nFor example\n\n```ts\ntype arr1 = ['a', 'b', 'c']\ntype arr2 = [3, 2, 1]\n\ntype tail1 = Last<arr1> // expected to be 'c'\ntype tail2 = Last<arr2> // expected to be 1\n```"},"template":"type Last<T extends any[]> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Last<[3, 2, 1]>, 1>>,\n Expect<Equal<Last<[() => 123, { a: string }]>, { a: string }>>,\n]\n"},{"no":16,"difficulty":"medium","path":"00016-medium-pop","info":{"zh-CN":{"title":"出堆"},"en":{"title":"Pop","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["array"],"related":["14","15"]}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n>在此挑战中建议使用TypeScript 4.0\n\n实现一个通用`Pop<T>`,它接受一个数组`T`并返回一个没有最后一个元素的数组。\n\n例如\n\n```ts\ntype arr1 = ['a', 'b', 'c', 'd']\ntype arr2 = [3, 2, 1]\n\ntype re1 = Pop<arr1> // expected to be ['a', 'b', 'c']\ntype re2 = Pop<arr2> // expected to be [3, 2]\n```\n\n**额外**:同样,您也可以实现`Shift`,`Push`和`Unshift`吗?","ja":"> この課題ではTypeScript 4.0が推奨されます\n\n配列 `T` を受け取り、最後の要素を除いた配列を返す汎用的な `Pop<T>` を実装してください。\n\n例えば\n\n```ts\ntype arr1 = ['a', 'b', 'c', 'd']\ntype arr2 = [3, 2, 1]\n\ntype re1 = Pop<arr1> // expected to be ['a', 'b', 'c']\ntype re2 = Pop<arr2> // expected to be [3, 2]\n```\n\n**おまけ**: 同様に `Shift`、 `Push`、 `Unshift` も実装できますか?","en":"> TypeScript 4.0 is recommended in this challenge\n\nImplement a generic `Pop<T>` that takes an Array `T` and returns an Array without it's last element.\n\nFor example\n\n```ts\ntype arr1 = ['a', 'b', 'c', 'd']\ntype arr2 = [3, 2, 1]\n\ntype re1 = Pop<arr1> // expected to be ['a', 'b', 'c']\ntype re2 = Pop<arr2> // expected to be [3, 2]\n```\n\n**Extra**: Similarly, can you implement `Shift`, `Push` and `Unshift` as well?"},"template":"type Pop<T extends any[]> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Pop<[3, 2, 1]>, [3, 2]>>,\n Expect<Equal<Pop<['a', 'b', 'c', 'd' ]>, ['a', 'b', 'c']>>,\n]\n"},{"no":17,"difficulty":"hard","path":"00017-hard-currying-1","info":{"zh-CN":{"title":"柯里化 1"},"en":{"title":"Currying 1","author":{"name":"Anthony Fu","email":"[email protected]","github":"antfu"},"tags":["array"],"related":["14","16","462"]}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n>在此挑战中建议使用TypeScript 4.0\n\n[Currying](https://en.wikipedia.org/wiki/Currying)是一种将带有多个参数的函数转换为每个带有一个参数的函数序列的技术。\n\n例如:\n\n```ts\nconst add = (a: number, b: number) => a + b\nconst three = add(1, 2)\n\nconst curriedAdd = Currying(add)\nconst five = curriedAdd(2)(3)\n```\n\n传递给`Currying`的函数可能有多个参数,您需要正确键入它。\n\n在此挑战中,curried函数一次仅接受一个参数。分配完所有参数后,它应返回其结果。","ja":"> この課題ではTypeScript 4.0が推奨されます\n\n[カリー化](https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96)とは、複数の引数を取る関数を、それぞれの 1 つの引数を取る関数の列に変換するテクニックです。\n\n例えば:\n\n```ts\nconst add = (a: number, b: number) => a + b\nconst three = add(1, 2)\n\nconst curriedAdd = Currying(add)\nconst five = curriedAdd(2)(3)\n```\n\n`Currying` に渡された関数は複数の引数を持つ場合があり、正しく型を付ける必要があります。\n\nこの課題では、カリー化された関数は一度に 1 つの引数しか受け付けません。すべての引数が代入されたら、その結果を返す必要があります。","en":"> TypeScript 4.0 is recommended in this challenge\n\n[Currying](https://en.wikipedia.org/wiki/Currying) is the technique of converting a function that takes multiple arguments into a sequence of functions that each take a single argument. \n\nFor example:\n\n```ts\nconst add = (a: number, b: number) => a + b\nconst three = add(1, 2)\n\nconst curriedAdd = Currying(add)\nconst five = curriedAdd(2)(3)\n```\n\nThe function passed to `Currying` may have multiple arguments, you need to correctly type it.\n\nIn this challenge, the curried function only accept one argument at a time. Once all the argument is assigned, it should return its result."},"template":"declare function Currying(fn: any): any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nconst curried1 = Currying((a: string, b: number, c: boolean) => true)\nconst curried2 = Currying((a: string, b: number, c: boolean, d: boolean, e: boolean, f: string, g: boolean) => true)\n\ntype cases = [\n Expect<Equal<\n typeof curried1, (a: string) => (b: number) => (c: boolean) => true\n >>,\n Expect<Equal<\n typeof curried2, (a: string) => (b: number) => (c: boolean) => (d: boolean) => (e: boolean) => (f: string) => (g: boolean) => true\n >>,\n]\n"},{"no":18,"difficulty":"easy","path":"00018-easy-tuple-length","info":{"zh-CN":{"title":"获取元组长度"},"en":{"title":"Length of Tuple","author":{"name":"sinoon","email":"[email protected]","github":"sinoon"},"tags":["tuple"]}},"readme":{"zh-CN":"> 欢迎 PR 改进翻译质量。\n\n创建一个通用的`Length`,接受一个`readonly`的数组,返回这个数组的长度。\n\n例如:\n\n```ts\ntype tesla = ['tesla', 'model 3', 'model X', 'model Y']\ntype spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT']\n\ntype teslaLength = Length<tesla> // expected 4\ntype spaceXLength = Length<spaceX> // expected 5\n```","ja":"タプル`T`を受け取り、そのタプルの長さを返す型`Length<T>`を実装します。\n\n例えば\n\n```ts\ntype tesla = ['tesla', 'model 3', 'model X', 'model Y']\ntype spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT']\n\ntype teslaLength = Length<tesla> // expected 4\ntype spaceXLength = Length<spaceX> // expected 5\n```","ko":"배열(튜플)을 받아 길이를 반환하는 제네릭 `Length<T>`를 구현하세요.\n\n예시:\n\n```ts\ntype tesla = ['tesla', 'model 3', 'model X', 'model Y']\ntype spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT']\n\ntype teslaLength = Length<tesla> // expected 4\ntype spaceXLength = Length<spaceX> // expected 5\n```","en":"For given a tuple, you need create a generic `Length`, pick the length of the tuple\n\nFor example\n\n```ts\ntype tesla = ['tesla', 'model 3', 'model X', 'model Y']\ntype spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT']\n\ntype teslaLength = Length<tesla> // expected 4\ntype spaceXLength = Length<spaceX> // expected 5\n```"},"template":"type Length<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nconst tesla = ['tesla', 'model 3', 'model X', 'model Y'] as const\nconst spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT'] as const\n\ntype cases = [\n Expect<Equal<Length<typeof tesla>, 4>>,\n Expect<Equal<Length<typeof spaceX>, 5>>,\n // @ts-expect-error\n Length<5>,\n // @ts-expect-error\n Length<'hello world'>,\n]\n"},{"no":20,"difficulty":"medium","path":"00020-medium-promise-all","info":{"en":{"difficulty":"medium","title":"Promise.all","tags":["array","built-in"],"author":{"github":"antfu","name":"Anthony Fu"}}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n键入函数`PromiseAll`,它接受PromiseLike对象数组,返回值应为`Promise<T>`,其中`T`是解析的结果数组。\n\n```ts\nconst promise1 = Promise.resolve(3);\nconst promise2 = 42;\nconst promise3 = new Promise<string>((resolve, reject) => {\n setTimeout(resolve, 100, 'foo');\n});\n\n// expected to be `Promise<[number, 42, string]>`\nconst p = Promise.all([promise1, promise2, promise3] as const)\n```","ja":"Promise ライクなオブジェクトの配列を受け取る関数 `PromiseAll` に型を付けてください。戻り値は `Promise<T>` である必要があります。ここで、`T` は解決された結果の配列です。\n\n```ts\nconst promise1 = Promise.resolve(3);\nconst promise2 = 42;\nconst promise3 = new Promise<string>((resolve, reject) => {\n setTimeout(resolve, 100, 'foo');\n});\n\n// expected to be `Promise<[number, 42, string]>`\nconst p = Promise.all([promise1, promise2, promise3] as const)\n```","en":"Type the function `PromiseAll` that accepts an array of PromiseLike objects, the returning value should be `Promise<T>` where `T` is the resolved result array.\n\n```ts\nconst promise1 = Promise.resolve(3);\nconst promise2 = 42;\nconst promise3 = new Promise<string>((resolve, reject) => {\n setTimeout(resolve, 100, 'foo');\n});\n\n// expected to be `Promise<[number, 42, string]>`\nconst p = Promise.all([promise1, promise2, promise3] as const)\n```"},"template":"declare function PromiseAll(values: any): any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nconst promiseAllTest1 = PromiseAll([1, 2, 3] as const)\nconst promiseAllTest2 = PromiseAll([1, 2, Promise.resolve(3)] as const)\nconst promiseAllTest3 = PromiseAll([1, 2, Promise.resolve(3)])\n\ntype cases = [\n Expect<Equal<typeof promiseAllTest1, Promise<[1, 2, 3]>>>,\n Expect<Equal<typeof promiseAllTest2, Promise<[1, 2, number]>>>,\n Expect<Equal<typeof promiseAllTest3, Promise<[number, number, number]>>>,\n]\n"},{"no":43,"difficulty":"easy","path":"00043-easy-exclude","info":{"en":{"difficulty":"easy","title":"Exclude","author":{"github":"zheeeng","name":"Zheeeng"},"tags":["built-in"]}},"readme":{"zh-CN":"> 欢迎 PR 改进翻译质量。\n\n实现内置的Exclude <T, U>类型,但不能直接使用它本身。\n>从联合类型T中排除U的类型成员,来构造一个新的类型。","ja":"組み込みの型ユーティリティ`Exclude <T, U>`を使用せず、`U`に割り当て可能な型を`T`から除外する型を実装します。","ko":"`T`에서 `U`에 할당할 수 있는 타입을 제외하는 내장 제네릭 `Exclude<T, U>`를 이를 사용하지 않고 구현하세요.","en":"Implement the built-in Exclude<T, U>\n> Exclude from T those types that are assignable to U"},"template":"type MyExclude<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<MyExclude<'a' | 'b' | 'c', 'a'>, Exclude<'a' | 'b' | 'c', 'a'>>>,\n Expect<Equal<MyExclude<'a' | 'b' | 'c', 'a' | 'b'>, Exclude<'a' | 'b' | 'c', 'a' | 'b'>>>,\n Expect<Equal<MyExclude<string | number | (() => void), Function>, Exclude<string | number | (() => void), Function>>>,\n]\n"},{"no":55,"difficulty":"hard","path":"00055-hard-union-to-intersection","info":{"en":{"difficulty":"hard","title":"Union to Intersection","tags":["utils","infer"],"author":{"github":"zheeeng","name":"Zheeeng"}}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n实现高级util类型`UnionToIntersection<U>`\n\n例如\n\n```ts\ntype I = Union2Intersection<'foo' | 42 | true> // expected to be 'foo' & 42 & true\n```","ja":"高度なユーティリティ型 `UnionToIntersection<U>` を実装してください。\n\n例えば\n\n```ts\ntype I = Union2Intersection<'foo' | 42 | true> // expected to be 'foo' & 42 & true\n```","en":"Implement the advanced util type `UnionToIntersection<U>`\n\nFor example\n\n```ts\ntype I = Union2Intersection<'foo' | 42 | true> // expected to be 'foo' & 42 & true\n```"},"template":"type UnionToIntersection<U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<UnionToIntersection<'foo' | 42 | true>, 'foo' & 42 & true>>,\n Expect<Equal<UnionToIntersection<(() => 'foo') | ((i: 42) => true)>, (() => 'foo') & ((i: 42) => true)>>,\n]\n"},{"no":57,"difficulty":"hard","path":"00057-hard-get-required","info":{"en":{"difficulty":"hard","title":"Get Required","tags":["utils","infer"],"author":{"github":"zheeeng","name":"Zheeeng"},"related":["59"]}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n实现高级util类型`GetRequired<T>`,该类型保留所有必填字段\n\n例如\n\n```ts\ntype I = GetRequired<{ foo: number, bar?: string }> // expected to be { foo: number }\n```","ja":"必須なフィールドのみを残す高度なユーティリティ型 `GetRequired<T>` を実装してください。\n\n例えば\n\n```ts\ntype I = GetRequired<{ foo: number, bar?: string }> // expected to be { foo: number }\n```","en":"Implement the advanced util type `GetRequired<T>`, which remains all the required fields\n\nFor example\n\n```ts\ntype I = GetRequired<{ foo: number, bar?: string }> // expected to be { foo: number }\n```"},"template":"type GetRequired<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<GetRequired<{ foo: number; bar?: string }>, { foo: number }>>,\n Expect<Equal<GetRequired<{ foo: undefined; bar?: undefined }>, { foo: undefined }>>,\n]\n"},{"no":59,"difficulty":"hard","path":"00059-hard-get-optional","info":{"en":{"difficulty":"hard","title":"Get Optional","tags":["utils","infer"],"author":{"github":"zheeeng","name":"Zheeeng"},"related":["57"]}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n实现高级util类型`GetOptional<T>`,该类型保留所有可选字段\n\n例如\n\n```ts\ntype I = GetOptional<{ foo: number, bar?: string }> // expected to be { bar?: string }\n```","ja":"オプショナルなフィールドのみを残す高度なユーティリティ型 `GetOptional<T>` を実装してください。\n\n例えば\n\n```ts\ntype I = GetOptional<{ foo: number, bar?: string }> // expected to be { bar?: string }\n```","en":"Implement the advanced util type `GetOptional<T>`, which remains all the optional fields\n\nFor example\n\n```ts\ntype I = GetOptional<{ foo: number, bar?: string }> // expected to be { bar?: string }\n```"},"template":"type GetOptional<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<GetOptional<{ foo: number; bar?: string }>, { bar?: string }>>,\n Expect<Equal<GetOptional<{ foo: undefined; bar?: undefined }>, { bar?: undefined }>>,\n]\n"},{"no":62,"difficulty":"medium","path":"00062-medium-type-lookup","info":{"en":{"difficulty":"medium","title":"Type Lookup","tags":["union","map"],"author":{"github":"antfu","name":"Anthony Fu"}}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n有时,您可能希望根据其属性在并集中查找类型。\n\n在此挑战中,我们想通过在联合`Cat | Dog`中搜索公共`type`字段来获取相应的类型。换句话说,在以下示例中,我们期望`LookUp<Dog | Cat, 'dog'>`获得`Dog`,`LookUp<Dog | Cat, 'cat'>`获得`Cat`。\n\n```ts\ninterface Cat {\n type: 'cat'\n breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'\n}\n\ninterface Dog {\n type: 'dog'\n breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'\n color: 'brown' | 'white' | 'black'\n}\n\ntype MyDog = LookUp<Cat | Dog, 'dog'> // expected to be `Dog`\n```","ja":"Union 型から特定の型を属性を使って取得したいことがあります。\n\nこの課題では、`Cat | Dog` という Union 型に共通する `type` というフィールドを使って、対応する型を取得します。つまり、以下の例のように、 `LookUp<Dog | Cat, 'dog'>` の場合は `Dog` を、`LookUp<Dog | Cat, 'cat'>` の場合は `Cat` を取得することになります。\n\n```ts\ninterface Cat {\n type: 'cat'\n breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'\n}\n\ninterface Dog {\n type: 'dog'\n breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'\n color: 'brown' | 'white' | 'black'\n}\n\ntype MyDog = LookUp<Cat | Dog, 'dog'> // expected to be `Dog`\n```","en":"Sometimes, you may want to lookup for a type in a union to by their attributes. \n\nIn this challenge, we would like to get the corresponding type by searching for the common `type` field in the union `Cat | Dog`. In other words, we will expect to get `Dog` for `LookUp<Dog | Cat, 'dog'>` and `Cat` for `LookUp<Dog | Cat, 'cat'>` in the following example.\n\n```ts\ninterface Cat {\n type: 'cat'\n breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'\n}\n\ninterface Dog {\n type: 'dog'\n breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'\n color: 'brown' | 'white' | 'black'\n}\n\ntype MyDogType = LookUp<Cat | Dog, 'dog'> // expected to be `Dog`\n```"},"template":"type LookUp<U, T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ninterface Cat {\n type: 'cat'\n breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'\n}\n\ninterface Dog {\n type: 'dog'\n breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'\n color: 'brown' | 'white' | 'black'\n}\n\ntype Animal = Cat | Dog\n\ntype cases = [\n Expect<Equal<LookUp<Animal, 'dog'>, Dog>>,\n Expect<Equal<LookUp<Animal, 'cat'>, Cat>>,\n]\n"},{"no":89,"difficulty":"hard","path":"00089-hard-required-keys","info":{"en":{"difficulty":"hard","title":"Required Keys","tags":["utils"],"related":["5"],"author":{"github":"yi-tuan","name":"yituan"}}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n实现高级util类型`RequiredKeys<T>`,该类型将所有必需的键都选择为一个并集。\n\n例如\n\n```ts\ntype Result = RequiredKeys<{ foo: number; bar?: string }>;\n// expected to be “foo”\n```","ja":"必須なキーの Union を抽出する高度なユーティリティ型 `RequiredKeys<T>` を実装してください。\n\n例えば\n\n```ts\ntype Result = RequiredKeys<{ foo: number; bar?: string }>;\n// expected to be “foo”\n```","en":"Implement the advanced util type `RequiredKeys<T>`, which picks all the required keys into a union.\n\nFor example\n\n```ts\ntype Result = RequiredKeys<{ foo: number; bar?: string }>;\n// expected to be “foo”\n```"},"template":"type RequiredKeys<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<RequiredKeys<{ a: number; b?: string }>, 'a'>>,\n Expect<Equal<RequiredKeys<{ a: undefined; b?: undefined }>, 'a'>>,\n Expect<Equal<RequiredKeys<{ a: undefined; b?: undefined; c: string; d: null }>, 'a' | 'c' | 'd'>>,\n Expect<Equal<RequiredKeys<{}>, never>>,\n]\n"},{"no":90,"difficulty":"hard","path":"00090-hard-optional-keys","info":{"en":{"difficulty":"hard","title":"Optional Keys","tags":["utils"],"related":["89","5"],"author":{"github":"yi-tuan","name":"yituan"}}},"readme":{"zh-CN":"> 由谷歌自动翻译,欢迎 PR 改进翻译质量。\n\n实现高级util类型`OptionalKeys<T>`,该类型将所有可选键合并为一个并集。","ja":"オプショナルなキーの Union を抽出する高度なユーティリティ型 `OptionalKeys<T>` を実装してください。","en":"Implement the advanced util type `OptionalKeys<T>`, which picks all the optional keys into a union."},"template":"type OptionalKeys<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<OptionalKeys<{ a: number; b?: string }>, 'b'>>,\n Expect<Equal<OptionalKeys<{ a: undefined; b?: undefined }>, 'b'>>,\n Expect<Equal<OptionalKeys<{ a: undefined; b?: undefined; c?: string; d?: null }>, 'b' | 'c' | 'd'>>,\n Expect<Equal<OptionalKeys<{}>, never>>,\n]\n"},{"no":106,"difficulty":"medium","path":"00106-medium-trimleft","info":{"en":{"difficulty":"medium","title":"Trim Left","tags":["template-literal"],"author":{"github":"antfu","name":"Anthony Fu"},"related":["108","4803"]}},"readme":{"zh-CN":"实现 `TrimLeft<T>` ,它接收确定的字符串类型并返回一个新的字符串,其中新返回的字符串删除了原字符串开头的空白字符串。\n\n例如\n\n```ts\ntype trimed = TrimLeft<' Hello World '> // 应推导出 'Hello World '\n```","ja":"文字列を受け取り、先頭の空白を削除した新しい文字列を返す `TrimLeft<T>` を実装します。\n\n例えば\n\n```ts\ntype trimed = TrimLeft<' Hello World '> // expected to be 'Hello World '\n```","en":"Implement `TrimLeft<T>` which takes an exact string type and returns a new string with the whitespace beginning removed.\n\nFor example\n\n```ts\ntype trimed = TrimLeft<' Hello World '> // expected to be 'Hello World '\n```"},"template":"type TrimLeft<S extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<TrimLeft<'str'>, 'str'>>,\n Expect<Equal<TrimLeft<' str'>, 'str'>>,\n Expect<Equal<TrimLeft<' str'>, 'str'>>,\n Expect<Equal<TrimLeft<' str '>, 'str '>>,\n Expect<Equal<TrimLeft<' \\n\\t foo bar '>, 'foo bar '>>,\n Expect<Equal<TrimLeft<''>, ''>>,\n Expect<Equal<TrimLeft<' \\n\\t'>, ''>>,\n]\n"},{"no":108,"difficulty":"medium","path":"00108-medium-trim","info":{"en":{"difficulty":"medium","title":"Trim","tags":["template-literal"],"author":{"github":"antfu","name":"Anthony Fu"},"related":["106","4803"]}},"readme":{"zh-CN":"实现`Trim<T>`,它是一个字符串类型,并返回一个新字符串,其中两端的空白符都已被删除。\n\n例如\n\n```ts\ntype trimed = Trim<' Hello World '> // expected to be 'Hello World'\n```","ja":"文字列を受け取り、両端の空白を削除した新しい文字列を返す `Trim<T>` を実装します。\n\n例えば\n\n```ts\ntype trimed = Trim<' Hello World '> // expected to be 'Hello World'\n```","en":"Implement `Trim<T>` which takes an exact string type and returns a new string with the whitespace from both ends removed.\n\nFor example\n\n```ts\ntype trimmed = Trim<' Hello World '> // expected to be 'Hello World'\n```"},"template":"type Trim<S extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Trim<'str'>, 'str'>>,\n Expect<Equal<Trim<' str'>, 'str'>>,\n Expect<Equal<Trim<' str'>, 'str'>>,\n Expect<Equal<Trim<'str '>, 'str'>>,\n Expect<Equal<Trim<' str '>, 'str'>>,\n Expect<Equal<Trim<' \\n\\t foo bar \\t'>, 'foo bar'>>,\n Expect<Equal<Trim<''>, ''>>,\n Expect<Equal<Trim<' \\n\\t '>, ''>>,\n]\n"},{"no":110,"difficulty":"medium","path":"00110-medium-capitalize","info":{"en":{"difficulty":"medium","title":"Capitalize","tags":["template-literal"],"author":{"github":"antfu","name":"Anthony Fu"}}},"readme":{"zh-CN":"实现 `Capitalize<T>` 它将字符串的第一个字母转换为大写,其余字母保持原样。\n\n例如\n\n```ts\ntype capitalized = Capitalize<'hello world'> // expected to be 'Hello world'\n```","ja":"文字列の最初の文字を大文字に変換し、それ以外はそのままにする `Capitalize<T>` を実装します。\n\n例えば\n\n```ts\ntype capitalized = Capitalize<'hello world'> // expected to be 'Hello world'\n```","en":"Implement `Capitalize<T>` which converts the first letter of a string to uppercase and leave the rest as-is.\n\nFor example\n\n```ts\ntype capitalized = Capitalize<'hello world'> // expected to be 'Hello world'\n```"},"template":"type MyCapitalize<S extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<MyCapitalize<'foobar'>, 'Foobar'>>,\n Expect<Equal<MyCapitalize<'FOOBAR'>, 'FOOBAR'>>,\n Expect<Equal<MyCapitalize<'foo bar'>, 'Foo bar'>>,\n Expect<Equal<MyCapitalize<''>, ''>>,\n Expect<Equal<MyCapitalize<'a'>, 'A'>>,\n Expect<Equal<MyCapitalize<'b'>, 'B'>>,\n Expect<Equal<MyCapitalize<'c'>, 'C'>>,\n Expect<Equal<MyCapitalize<'d'>, 'D'>>,\n Expect<Equal<MyCapitalize<'e'>, 'E'>>,\n Expect<Equal<MyCapitalize<'f'>, 'F'>>,\n Expect<Equal<MyCapitalize<'g'>, 'G'>>,\n Expect<Equal<MyCapitalize<'h'>, 'H'>>,\n Expect<Equal<MyCapitalize<'i'>, 'I'>>,\n Expect<Equal<MyCapitalize<'j'>, 'J'>>,\n Expect<Equal<MyCapitalize<'k'>, 'K'>>,\n Expect<Equal<MyCapitalize<'l'>, 'L'>>,\n Expect<Equal<MyCapitalize<'m'>, 'M'>>,\n Expect<Equal<MyCapitalize<'n'>, 'N'>>,\n Expect<Equal<MyCapitalize<'o'>, 'O'>>,\n Expect<Equal<MyCapitalize<'p'>, 'P'>>,\n Expect<Equal<MyCapitalize<'q'>, 'Q'>>,\n Expect<Equal<MyCapitalize<'r'>, 'R'>>,\n Expect<Equal<MyCapitalize<'s'>, 'S'>>,\n Expect<Equal<MyCapitalize<'t'>, 'T'>>,\n Expect<Equal<MyCapitalize<'u'>, 'U'>>,\n Expect<Equal<MyCapitalize<'v'>, 'V'>>,\n Expect<Equal<MyCapitalize<'w'>, 'W'>>,\n Expect<Equal<MyCapitalize<'x'>, 'X'>>,\n Expect<Equal<MyCapitalize<'y'>, 'Y'>>,\n Expect<Equal<MyCapitalize<'z'>, 'Z'>>,\n]\n"},{"no":112,"difficulty":"hard","path":"00112-hard-capitalizewords","info":{"en":{"difficulty":"hard","title":"Capitalize Words","tags":["template-literal"],"author":{"github":"antfu","name":"Anthony Fu"}}},"readme":{"ja":"**文字列の各単語**の最初の文字を大文字に変換し、残りをそのままにする `CapitalizeWords <T>` を実装します。\n\n例えば\n\n```ts\ntype capitalized = CapitalizeWords<'hello world, my friends'> // expected to be 'Hello World, My Friends'\n```","en":"Implement `CapitalizeWords<T>` which converts the first letter of **each word of a string** to uppercase and leaves the rest as-is.\n\nFor example\n\n```ts\ntype capitalized = CapitalizeWords<'hello world, my friends'> // expected to be 'Hello World, My Friends'\n```"},"template":"type CapitalizeWords<S extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<CapitalizeWords<'foobar'>, 'Foobar'>>,\n Expect<Equal<CapitalizeWords<'FOOBAR'>, 'FOOBAR'>>,\n Expect<Equal<CapitalizeWords<'foo bar'>, 'Foo Bar'>>,\n Expect<Equal<CapitalizeWords<'foo bar hello world'>, 'Foo Bar Hello World'>>,\n Expect<Equal<CapitalizeWords<'foo bar.hello,world'>, 'Foo Bar.Hello,World'>>,\n Expect<Equal<CapitalizeWords<''>, ''>>,\n]\n"},{"no":114,"difficulty":"hard","path":"00114-hard-camelcase","info":{"en":{"difficulty":"hard","title":"CamelCase","tags":["template-literal"],"author":{"github":"antfu","name":"Anthony Fu"},"related":["612"]}},"readme":{"ja":"`snake_case` 文字列を `camelCase` に変換する `CamelCase <T>` を実装します。\n\n例えば\n\n```ts\ntype camelCase1 = CamelCase<'hello_world_with_types'> // expected to be 'helloWorldWithTypes'\ntype camelCase2 = CamelCase<'HELLO_WORLD_WITH_TYPES'> // expected to be same as previous one\n```","en":"Implement `CamelCase<T>` which converts `snake_case` string to `camelCase`.\n\nFor example\n\n```ts\ntype camelCase1 = CamelCase<'hello_world_with_types'> // expected to be 'helloWorldWithTypes'\ntype camelCase2 = CamelCase<'HELLO_WORLD_WITH_TYPES'> // expected to be same as previous one\n```"},"template":"type CamelCase<S extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<CamelCase<'foobar'>, 'foobar'>>,\n Expect<Equal<CamelCase<'FOOBAR'>, 'foobar'>>,\n Expect<Equal<CamelCase<'foo_bar'>, 'fooBar'>>,\n Expect<Equal<CamelCase<'foo_bar_hello_world'>, 'fooBarHelloWorld'>>,\n Expect<Equal<CamelCase<'HELLO_WORLD_WITH_TYPES'>, 'helloWorldWithTypes'>>,\n Expect<Equal<CamelCase<'-'>, '-'>>,\n Expect<Equal<CamelCase<''>, ''>>,\n Expect<Equal<CamelCase<'😎'>, '😎'>>,\n]\n"},{"no":116,"difficulty":"medium","path":"00116-medium-replace","info":{"en":{"difficulty":"medium","title":"Replace","tags":["template-literal"],"author":{"github":"antfu","name":"Anthony Fu"}}},"readme":{"zh-CN":"实现 `Replace<S, From, To>` 将字符串 `S` 中的第一个子字符串 `From` 替换为 `To` 。\n\n例如\n\n```ts\ntype replaced = Replace<'types are fun!', 'fun', 'awesome'> // 期望是 'types are awesome!'\n```","ja":"文字列`S`に含まれる文字`From`を`To`に一度だけ置き換える型`Replace<S, From, To>`を実装します。\n\n例えば\n\n```ts\ntype replaced = Replace<'types are fun!', 'fun', 'awesome'>; // expected to be 'types are awesome!'\n```","en":"Implement `Replace<S, From, To>` which replace the string `From` with `To` once in the given string `S`\n\nFor example\n\n```ts\ntype replaced = Replace<'types are fun!', 'fun', 'awesome'> // expected to be 'types are awesome!'\n```"},"template":"type Replace<S extends string, From extends string, To extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Replace<'foobar', 'bar', 'foo'>, 'foofoo'>>,\n Expect<Equal<Replace<'foobarbar', 'bar', 'foo'>, 'foofoobar'>>,\n Expect<Equal<Replace<'foobarbar', '', 'foo'>, 'foobarbar'>>,\n Expect<Equal<Replace<'foobarbar', 'bar', ''>, 'foobar'>>,\n Expect<Equal<Replace<'foobarbar', 'bra', 'foo'>, 'foobarbar'>>,\n Expect<Equal<Replace<'', '', ''>, ''>>,\n]\n"},{"no":119,"difficulty":"medium","path":"00119-medium-replaceall","info":{"en":{"difficulty":"medium","title":"ReplaceAll","tags":["template-literal"],"author":{"github":"antfu","name":"Anthony Fu"}}},"readme":{"zh-CN":"实现 `ReplaceAll<S, From, To>` 将一个字符串 `S` 中的所有子字符串 `From` 替换为 `To`。\n\n例如\n\n```ts\ntype replaced = ReplaceAll<'t y p e s', ' ', ''> // 期望是 'types'\n```","ja":"文字列`S`に含まれる部分文字列`From`を`To`に置き換える型`ReplaceAll<S, From, To>`を実装します。\n\n例えば\n\n```ts\ntype replaced = ReplaceAll<'t y p e s', ' ', ''>; // expected to be 'types'\n```","en":"Implement `ReplaceAll<S, From, To>` which replace the all the substring `From` with `To` in the given string `S`\n\nFor example\n\n```ts\ntype replaced = ReplaceAll<'t y p e s', ' ', ''> // expected to be 'types'\n```"},"template":"type ReplaceAll<S extends string, From extends string, To extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<ReplaceAll<'foobar', 'bar', 'foo'>, 'foofoo'>>,\n Expect<Equal<ReplaceAll<'foobar', 'bag', 'foo'>, 'foobar'>>,\n Expect<Equal<ReplaceAll<'foobarbar', 'bar', 'foo'>, 'foofoofoo'>>,\n Expect<Equal<ReplaceAll<'t y p e s', ' ', ''>, 'types'>>,\n Expect<Equal<ReplaceAll<'foobarbar', '', 'foo'>, 'foobarbar'>>,\n Expect<Equal<ReplaceAll<'barfoo', 'bar', 'foo'>, 'foofoo'>>,\n Expect<Equal<ReplaceAll<'foobarfoobar', 'ob', 'b'>, 'fobarfobar'>>,\n Expect<Equal<ReplaceAll<'foboorfoboar', 'bo', 'b'>, 'foborfobar'>>,\n Expect<Equal<ReplaceAll<'', '', ''>, ''>>,\n]\n"},{"no":147,"difficulty":"hard","path":"00147-hard-c-printf-parser","info":{"en":{"difficulty":"hard","title":"C-printf Parser","tags":["template-literal"],"author":{"github":"g-plane","name":"Pig Fang"}}},"readme":{"ja":"C 言語には`printf`という関数があり、以下のようにフォーマットして出力してくれます。\n\n```c\nprintf(\"The result is %d.\", 42);\n```\n\nこの課題では、入力値の文字列をパースして`%d`や`%f`のようなフォーマットのプレースホルダーを抜き出します。\n例えば、もし入力文字列が`\"The result is %d\"`であるなら、パースした結果は`['dec']`というタプルになります。\n\nマッピングは以下となります。\n\n```typescript\ntype ControlsMap = {\n c: 'char';\n s: 'string';\n d: 'dec';\n o: 'oct';\n h: 'hex';\n f: 'float';\n p: 'pointer';\n};\n```","en":"There is a function in C language: `printf`. This function allows us to print something with formatting. Like this:\n\n```c\nprintf(\"The result is %d.\", 42);\n```\n\nThis challenge requires you to parse the input string and extract the format placeholders like `%d` and `%f`. For example, if the input string is `\"The result is %d.\"`, the parsed result is a tuple `['dec']`.\n\nHere is the mapping:\n\n```typescript\ntype ControlsMap = {\n c: 'char',\n s: 'string',\n d: 'dec',\n o: 'oct',\n h: 'hex',\n f: 'float',\n p: 'pointer',\n}\n```"},"template":"type ControlsMap = {\n c: 'char'\n s: 'string'\n d: 'dec'\n o: 'oct'\n h: 'hex'\n f: 'float'\n p: 'pointer'\n}\n\ntype ParsePrintFormat = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<ParsePrintFormat<''>, []>>,\n Expect<Equal<ParsePrintFormat<'Any string.'>, []>>,\n Expect<Equal<ParsePrintFormat<'The result is %d.'>, ['dec']>>,\n Expect<Equal<ParsePrintFormat<'The result is %%d.'>, []>>,\n Expect<Equal<ParsePrintFormat<'The result is %%%d.'>, ['dec']>>,\n Expect<Equal<ParsePrintFormat<'The result is %f.'>, ['float']>>,\n Expect<Equal<ParsePrintFormat<'The result is %h.'>, ['hex']>>,\n Expect<Equal<ParsePrintFormat<'The result is %q.'>, []>>,\n Expect<Equal<ParsePrintFormat<'Hello %s: score is %d.'>, ['string', 'dec']>>,\n Expect<Equal<ParsePrintFormat<'The result is %'>, []>>,\n]\n"},{"no":151,"difficulty":"extreme","path":"00151-extreme-query-string-parser","info":{"en":{"difficulty":"extreme","title":"Query String Parser","tags":["template-literal"],"author":{"github":"g-plane","name":"Pig Fang"}}},"readme":{"en":"You're required to implement a type-level parser to parse URL query string into a object literal type.\n\nSome detailed requirements:\n\n- Value of a key in query string can be ignored but still be parsed to `true`. For example, `'key'` is without value, so the parser result is `{ key: true }`.\n- Duplicated keys must be merged into one. If there are different values with the same key, values must be merged into a tuple type.\n- When a key has only one value, that value can't be wrapped into a tuple type.\n- If values with the same key appear more than once, it must be treated as once. For example, `key=value&key=value` must be treated as `key=value` only."},"template":"type ParseQueryString = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<ParseQueryString<''>, {}>>,\n Expect<Equal<ParseQueryString<'k1'>, { k1: true }>>,\n Expect<Equal<ParseQueryString<'k1&k1'>, { k1: true }>>,\n Expect<Equal<ParseQueryString<'k1&k2'>, { k1: true; k2: true }>>,\n Expect<Equal<ParseQueryString<'k1=v1'>, { k1: 'v1' }>>,\n Expect<Equal<ParseQueryString<'k1=v1&k1=v2'>, { k1: ['v1', 'v2'] }>>,\n Expect<Equal<ParseQueryString<'k1=v1&k2=v2'>, { k1: 'v1'; k2: 'v2' }>>,\n Expect<Equal<ParseQueryString<'k1=v1&k2=v2&k1=v2'>, { k1: ['v1', 'v2']; k2: 'v2' }>>,\n Expect<Equal<ParseQueryString<'k1=v1&k2'>, { k1: 'v1'; k2: true }>>,\n Expect<Equal<ParseQueryString<'k1=v1&k1=v1'>, { k1: 'v1' }>>,\n]\n"},{"no":189,"difficulty":"easy","path":"00189-easy-awaited","info":{"en":{"difficulty":"easy","title":"Awaited","tags":["promise","built-in"],"editor":{"github":"sinoon","name":"sinoon"},"author":{"github":"maciejsikora","name":"Maciej Sikora"}}},"readme":{"zh-CN":"假如我们有一个 Promise 对象,这个 Promise 对象会返回一个类型。在 TS 中,我们用 Promise<T> 中的 T 来描述这个 Promise 返回的类型。请你实现一个类型,可以获取这个类型。\n\n比如:`Promise<ExampleType>`,请你返回 ExampleType 类型。\n\n> 这个挑战来自于 [@maciejsikora](https://github.com/maciejsikora) 的文章:[original article](https://dev.to/macsikora/advanced-typescript-exercises-question-1-45k4)","ja":"Promise ライクな型が内包する型をどのように取得すればよいでしょうか。\n例えば、`Promise<ExampleType>`という型がある場合、どのようにして ExampleType を取得すればよいでしょうか。\n\n> この問題の元記事は [original article](https://dev.to/macsikora/advanced-typescript-exercises-question-1-45k4) by [@maciejsikora](https://github.com/maciejsikora) です。","ko":"Promise와 같은 타입에 감싸인 타입이 있을 때, 안에 감싸인 타입이 무엇인지 어떻게 알 수 있을까요? 예를 들어 `Promise<ExampleType>`이 있을 때, `ExampleType`을 어떻게 얻을 수 있을까요?\n\n> 출처: [original article](https://dev.to/macsikora/advanced-typescript-exercises-question-1-45k4) by [@maciejsikora](https://github.com/maciejsikora)","en":"If we have a type which is wrapped type like Promise. How we can get a type which is inside the wrapped type? For example if we have `Promise<ExampleType>` how to get ExampleType?\n\n> This question is ported from the [original article](https://dev.to/macsikora/advanced-typescript-exercises-question-1-45k4) by [@maciejsikora](https://github.com/maciejsikora)"},"template":"type MyAwaited = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype X = Promise<string>\ntype Y = Promise<{ field: number }>\ntype Z = Promise<Promise<string | number>>\n\ntype cases = [\n Expect<Equal<MyAwaited<X>, string>>,\n Expect<Equal<MyAwaited<Y>, { field: number }>>,\n Expect<Equal<MyAwaited<Z>, string | number>>,\n]\n\n// @ts-expect-error\ntype error = MyAwaited<number>\n"},{"no":191,"difficulty":"medium","path":"00191-medium-append-argument","info":{"zh-CN":{"title":"追加参数"},"en":{"difficulty":"medium","title":"Append Argument","editor":{"github":"sinoon","name":"sinoon"},"author":{"github":"maciejsikora","name":"Maciej Sikora"},"tags":["arguments"]}},"readme":{"zh-CN":"> 由 @antfu 翻译\n\n实现一个泛型 `AppendArgument<Fn, A>`,对于给定的函数类型 `Fn`,以及一个任意类型 `A`,返回一个新的函数 `G`。`G` 拥有 `Fn` 的所有参数并在末尾追加类型为 `A` 的参数。\n\n```typescript\ntype Fn = (a: number, b: string) => number\n\ntype Result = AppendArgument<Fn, boolean> \n// 期望是 (a: number, b: string, x: boolean) => number\n```\n\n> 本挑战来自于 [@maciejsikora](https://github.com/maciejsikora) 在 Dev.io 上的[文章](https://dev.to/macsikora/advanced-typescript-exercises-question-4-495c)","ja":"与えられた関数型 `Fn` と任意の型 `A` に対して、第一引数に `Fn` を取り、第二引数に `A` を取り、`Fn` の引数に `A` を追加した関数型 `G` を生成します。\n\n例えば、\n\n```typescript\ntype Fn = (a: number, b: string) => number\n\ntype Result = AppendArgument<Fn, boolean> \n// expected be (a: number, b: string, x: boolean) => number\n```\n\n> この質問は、[@maciejsikora](https://github.com/maciejsikora) による[元の記事](https://dev.to/macsikora/advanced-typescript-exercises-question-4-495c)から移植されました。","en":"For given function type `Fn`, and any type `A` (any in this context means we don't restrict the type, and I don't have in mind any type 😉) create a generic type which will take `Fn` as the first argument, `A` as the second, and will produce function type `G` which will be the same as `Fn` but with appended argument `A` as a last one.\n\nFor example,\n\n```typescript\ntype Fn = (a: number, b: string) => number\n\ntype Result = AppendArgument<Fn, boolean> \n// expected be (a: number, b: string, x: boolean) => number\n```\n\n> This question is ported from the [original article](https://dev.to/macsikora/advanced-typescript-exercises-question-4-495c) by [@maciejsikora](https://github.com/maciejsikora)"},"template":"type AppendArgument<Fn, A> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype Case1 = AppendArgument<(a: number, b: string) => number, boolean>\ntype Result1 = (a: number, b: string, x: boolean) => number\n\ntype Case2 = AppendArgument<() => void, undefined>\ntype Result2 = (x: undefined) => void\n\ntype cases = [\n Expect<Equal<Case1, Result1>>,\n Expect<Equal<Case2, Result2>>,\n]\n"},{"no":213,"difficulty":"hard","path":"00213-hard-vue-basic-props","info":{"en":{"difficulty":"hard","title":"Vue Basic Props","tags":["vue","application"],"related":["6"],"author":{"github":"antfu","name":"Anthony Fu"}}},"readme":{"ja":"**この問題は [6 - Simple Vue](//tsch.js.org/6) の続きです。 先にその問題を解いた上で、そこで得られるコードを基盤にしてこの問題に取り組んでください。**\n\nSimple Vue に加え、我々は 新しく `props` フィールドをオプションとして利用できます。これは Vue の `props` オプションを更に簡潔にしたものです。利用するにはいくつかのルールがあります。\n\n`props` は、 `this` に挿入された各々のフィールドをキーをとして保持するオブジェクトです。挿入された props は `data`,`computed`, `methods` などを始めとした 全ての環境からアクセス可能になります。\n\nprop は コンストラクタ、または コンストラクタを含んだ `type` フィールドを持つオブジェクトで定義されます。\n\n例)\n\n```js\nprops: {\n foo: Boolean\n}\n// or\nprops: {\n foo: { type: Boolean }\n}\n```\n\nこれらは `type Props = { foo: boolean }` であると推測されます。\n\n複数の型を渡した場合、Props の型は ユニオン型として推測されます。\n\n```ts\nprops: {\n foo: { type: [Boolean, Number, String] }\n}\n// -->\ntype Props = { foo: boolean | number | string }\n```\n\n空のオブジェクトが渡された場合、対象のkeyは `any` 型として推測されます。\n\n\nより具体的なケースについては, Test Cases セクションを参照してください。\n\n>Vue の `required`, `default`, そして 配列の props はこの問題において考慮されておりません.","en":"**This challenge continues from [6 - Simple Vue](//tsch.js.org/6), you should finish that one first, and modify your code based on it to start this challenge**.\n\nIn addition to the Simple Vue, we are now having a new `props` field in the options. This is a simplified version of Vue's `props` option. Here are some of the rules.\n\n`props` is an object containing each field as the key of the real props injected into `this`. The injected props will be accessible in all the context including `data`, `computed`, and `methods`.\n\nA prop will be defined either by a constructor or an object with a `type` field containing constructor(s).\n\nFor example\n\n```js\nprops: {\n foo: Boolean\n}\n// or\nprops: {\n foo: { type: Boolean }\n}\n```\n\nshould be inferred to `type Props = { foo: boolean }`.\n\nWhen passing multiple constructors, the type should be inferred to a union.\n\n```ts\nprops: {\n foo: { type: [Boolean, Number, String] }\n}\n// -->\ntype Props = { foo: boolean | number | string }\n```\n\nWhen an empty object is passed, the key should be inferred to `any`.\n\nFor more specified cases, check out the Test Cases section.\n\n> `required`, `default`, and array props in Vue are not considered in this challenge."},"template":"declare function VueBasicProps(options: any): any\n","tests":"import type { Debug, Equal, Expect, IsAny } from '@type-challenges/utils'\n\nclass ClassA {}\n\nVueBasicProps({\n props: {\n propA: {},\n propB: { type: String },\n propC: { type: Boolean },\n propD: { type: ClassA },\n propE: { type: [String, Number] },\n propF: RegExp,\n },\n data(this) {\n type PropsType = Debug<typeof this>\n type cases = [\n Expect<IsAny<PropsType['propA']>>,\n Expect<Equal<PropsType['propB'], string>>,\n Expect<Equal<PropsType['propC'], boolean>>,\n Expect<Equal<PropsType['propD'], ClassA>>,\n Expect<Equal<PropsType['propE'], string | number>>,\n Expect<Equal<PropsType['propF'], RegExp>>,\n ]\n\n // @ts-expect-error\n this.firstname\n // @ts-expect-error\n this.getRandom()\n // @ts-expect-error\n this.data()\n\n return {\n firstname: 'Type',\n lastname: 'Challenges',\n amount: 10,\n }\n },\n computed: {\n fullname() {\n return `${this.firstname} ${this.lastname}`\n },\n },\n methods: {\n getRandom() {\n return Math.random()\n },\n hi() {\n alert(this.fullname.toLowerCase())\n alert(this.getRandom())\n },\n test() {\n const fullname = this.fullname\n const propE = this.propE\n type cases = [\n Expect<Equal<typeof fullname, string>>,\n Expect<Equal<typeof propE, string | number>>,\n ]\n },\n },\n})\n"},{"no":216,"difficulty":"extreme","path":"00216-extreme-slice","info":{"en":{"difficulty":"extreme","title":"Slice","tags":["array"],"author":{"github":"antfu","name":"Anthony Fu"}}},"readme":{"en":"Implement the JavaScript `Array.slice` function in the type system. `Slice<Arr, Start, End>` takes the three argument. The output should be a subarray of `Arr` from index `Start` to `End`. Indexes with negative numbers should be counted from reversely.\n\nFor example\n\n```ts\ntype Arr = [1, 2, 3, 4, 5]\ntype Result = Slice<Arr, 2, 4> // expected to be [3, 4]\n```"},"template":"type Slice<Arr, Start, End> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype Arr = [1, 2, 3, 4, 5]\n\ntype cases = [\n // basic\n Expect<Equal<Slice<Arr, 0, 1>, [1]>>,\n Expect<Equal<Slice<Arr, 0, 0>, []>>,\n Expect<Equal<Slice<Arr, 2, 4>, [3, 4]>>,\n\n // optional args\n Expect<Equal<Slice<[]>, []>>,\n Expect<Equal<Slice<Arr>, Arr>>,\n Expect<Equal<Slice<Arr, 0>, Arr>>,\n Expect<Equal<Slice<Arr, 2>, [3, 4, 5]>>,\n\n // negative index\n Expect<Equal<Slice<Arr, 0, -1>, [1, 2, 3, 4]>>,\n Expect<Equal<Slice<Arr, -3, -1>, [3, 4]>>,\n\n // invalid\n Expect<Equal<Slice<Arr, 10>, []>>,\n Expect<Equal<Slice<Arr, 1, 0>, []>>,\n Expect<Equal<Slice<Arr, 10, 20>, []>>,\n]\n"},{"no":223,"difficulty":"hard","path":"00223-hard-isany","info":{"en":{"difficulty":"hard","title":"IsAny","tags":["utils"],"author":{"github":"pashutk","name":"Pavel Glushkov"},"related":["1042","1097","4484"]}},"readme":{"ja":"`any`型の値を持っているかを検出することが便利な場合があります。これは、モジュール API で`any`型の値をエクスポート可能なサードーパーティーの TypeScript モジュールを使用する際に\n特に便利です。また、implicitAny チェックを抑制する際に`any`型について知ることは良いことです。\n\nそこで、型`T`を受け取るユーティリティ型`IsAny<T>`を書いてみましょう。`T`が`any`型であれば`true`を返し、そうでなければ`false`を返します。","en":"Sometimes it's useful to detect if you have a value with `any` type. This is especially helpful while working with third-party Typescript modules, which can export `any` values in the module API. It's also good to know about `any` when you're suppressing implicitAny checks.\n\nSo, let's write a utility type `IsAny<T>`, which takes input type `T`. If `T` is `any`, return `true`, otherwise, return `false`."},"template":"type IsAny<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<IsAny<any>, true>>,\n\n Expect<Equal<IsAny<undefined>, false>>,\n Expect<Equal<IsAny<unknown>, false>>,\n Expect<Equal<IsAny<never>, false>>,\n Expect<Equal<IsAny<string>, false>>,\n]\n"},{"no":268,"difficulty":"easy","path":"00268-easy-if","info":{"en":{"difficulty":"easy","title":"If","tags":["utils"],"author":{"github":"pashutk","name":"Pavel Glushkov"}}},"readme":{"zh-CN":"实现一个 `IF` 类型,它接收一个条件类型 `C` ,一个判断为真时的返回类型 `T` ,以及一个判断为假时的返回类型 `F`。 `C` 只能是 `true` 或者 `false`, `T` 和 `F` 可以是任意类型。\n\n举例:\n\n```ts\ntype A = If<true, 'a', 'b'> // expected to be 'a'\ntype B = If<false, 'a', 'b'> // expected to be 'b'\n```","ja":"条件値`C`、 `C`が truthy である場合の戻り値の型`T`、`C`が falsy である場合の戻り値の型`F`を受け取る`If`を実装します。\n条件値`C` は`true`か`false`のどちらかであることが期待されますが、`T` と `F` は任意の型をとることができます。\n\n例えば\n\n```ts\ntype A = If<true, 'a', 'b'>; // expected to be 'a'\ntype B = If<false, 'a', 'b'>; // expected to be 'b'\n```","ko":"조건 `C`, 참일 때 반환하는 타입 `T`, 거짓일 때 반환하는 타입 `F`를 받는 타입 `If`를 구현하세요. `C`는 `true` 또는 `false`이고, `T`와 `F`는 아무 타입입니다.\n\n예시:\n\n```ts\ntype A = If<true, 'a', 'b'> // expected to be 'a'\ntype B = If<false, 'a', 'b'> // expected to be 'b'\n```","en":"Implement a utils `If` which accepts condition `C`, a truthy return type `T`, and a falsy return type `F`. `C` is expected to be either `true` or `false` while `T` and `F` can be any type.\n\nFor example:\n\n```ts\ntype A = If<true, 'a', 'b'> // expected to be 'a'\ntype B = If<false, 'a', 'b'> // expected to be 'b'\n```"},"template":"type If<C, T, F> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<If<true, 'a', 'b'>, 'a'>>,\n Expect<Equal<If<false, 'a', 2>, 2>>,\n]\n\n// @ts-expect-error\ntype error = If<null, 'a', 'b'>\n"},{"no":270,"difficulty":"hard","path":"00270-hard-typed-get","info":{"en":{"difficulty":"hard","title":"Typed Get","tags":["utils","template-literal"],"author":{"github":"antfu","name":"Anthony Fu"}}},"readme":{"ja":"[lodash の get 関数](https://lodash.com/docs/4.17.15#get)は JavaScript でネストした値にアクセスする際にとても便利です。しかし、TypeScript でこのような関数を使うと型情報が失われてしまいます。\nTypeScript4.1 の機能である[Template Literal Types](https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-beta/#template-literal-types)を使うと、`get`の適切な型付けが可能となります。\nこれを実装できるでしょうか?\n\n例えば、\n\n```ts\ntype Data = {\n foo: {\n bar: {\n value: 'foobar';\n count: 6;\n };\n included: true;\n };\n hello: 'world';\n};\ntype A = Get<Data, 'hello'>; // 'world'\ntype B = Get<Data, 'foo.bar.count'>; // 6\ntype C = Get<Data, 'foo.bar'>; // { value: 'foobar', count: 6 }\n```\n\nこの課題では、配列へのアクセスは必要ありません。","en":"The [`get` function in lodash](https://lodash.com/docs/4.17.15#get) is a quite convenient helper for accessing nested values in JavaScript. However, when we come to TypeScript, using functions like this will make you lose the type information. With TS 4.1's upcoming [Template Literal Types](https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-beta/#template-literal-types) feature, properly typing `get` becomes possible. Can you implement it?\n\nFor example,\n\n```ts\ntype Data = {\n foo: {\n bar: {\n value: 'foobar',\n count: 6,\n },\n included: true,\n },\n hello: 'world'\n}\n \ntype A = Get<Data, 'hello'> // 'world'\ntype B = Get<Data, 'foo.bar.count'> // 6\ntype C = Get<Data, 'foo.bar'> // { value: 'foobar', count: 6 }\n```\n\nAccessing arrays is not required in this challenge."},"template":"type Get<T, K> = string\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Get<Data, 'hello'>, 'world'>>,\n Expect<Equal<Get<Data, 'foo.bar.count'>, 6>>,\n Expect<Equal<Get<Data, 'foo.bar'>, { value: 'foobar'; count: 6 }>>,\n\n Expect<Equal<Get<Data, 'no.existed'>, never>>,\n]\n\ntype Data = {\n foo: {\n bar: {\n value: 'foobar'\n count: 6\n }\n included: true\n }\n hello: 'world'\n}\n"},{"no":274,"difficulty":"extreme","path":"00274-extreme-integers-comparator","info":{"en":{"difficulty":"extreme","title":"Integers Comparator","tags":["template-literal","math"],"author":{"github":"g-plane","name":"Pig Fang"}}},"readme":{"en":"Implement a type-level integers comparator. We've provided an enum for indicating the comparison result, like this:\n\n- If `a` is greater than `b`, type should be `Comparison.Greater`.\n- If `a` and `b` are equal, type should be `Comparison.Equal`.\n- If `a` is lower than `b`, type should be `Comparison.Lower`.\n\n**Note that `a` and `b` can be positive integers or negative integers or zero, even one is positive while another one is negative.**"},"template":"enum Comparison {\n Greater,\n Equal,\n Lower,\n}\n\ntype Comparator<A extends number, B extends number> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Comparator<5, 5>, Comparison.Equal>>,\n Expect<Equal<Comparator<5, 6>, Comparison.Lower>>,\n Expect<Equal<Comparator<5, 8>, Comparison.Lower>>,\n Expect<Equal<Comparator<5, 0>, Comparison.Greater>>,\n Expect<Equal<Comparator<-5, 0>, Comparison.Lower>>,\n Expect<Equal<Comparator<0, 0>, Comparison.Equal>>,\n Expect<Equal<Comparator<0, -5>, Comparison.Greater>>,\n Expect<Equal<Comparator<5, -3>, Comparison.Greater>>,\n Expect<Equal<Comparator<5, -7>, Comparison.Greater>>,\n Expect<Equal<Comparator<-5, -7>, Comparison.Greater>>,\n Expect<Equal<Comparator<-5, -3>, Comparison.Lower>>,\n Expect<Equal<Comparator<-25, -30>, Comparison.Greater>>,\n Expect<Equal<Comparator<15, -23>, Comparison.Greater>>,\n Expect<Equal<Comparator<40, 37>, Comparison.Greater>>,\n Expect<Equal<Comparator<-36, 36>, Comparison.Lower>>,\n Expect<Equal<Comparator<27, 27>, Comparison.Equal>>,\n Expect<Equal<Comparator<-38, -38>, Comparison.Equal>>,\n]\n"},{"no":296,"difficulty":"medium","path":"00296-medium-permutation","info":{"en":{"difficulty":"medium","title":"Permutation","tags":["union"],"author":{"github":"pandanoir","name":"Naoto Ikuno"}}},"readme":{"zh-CN":"实现联合类型的全排列,将联合类型转换成所有可能的全排列数组的联合类型。\n\n```typescript\ntype perm = Permutation<'A' | 'B' | 'C'>; // ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']\n```","ja":"Union 型を Union 型の値の順列を含む配列に変換する順列型を実装します。\n\n```typescript\ntype perm = Permutation<'A' | 'B' | 'C'>; // ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']\n```","en":"Implement permutation type that transforms union types into the array that includes permutations of unions.\n\n```typescript\ntype perm = Permutation<'A' | 'B' | 'C'>; // ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']\n```"},"template":"type Permutation<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Permutation<'A'>, ['A']>>,\n Expect<Equal<Permutation<'A' | 'B' | 'C'>, ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']>>,\n Expect<Equal<Permutation<'B' | 'A' | 'C'>, ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']>>,\n Expect<Equal<Permutation<never>, []>>,\n]\n"},{"no":298,"difficulty":"medium","path":"00298-medium-length-of-string","info":{"en":{"difficulty":"medium","title":"Length of String","tags":["template-literal"],"author":{"github":"g-plane","name":"Pig Fang"}}},"readme":{"zh-CN":"计算字符串的长度,类似于 `String#length` 。","ja":"`String#length` と同じように、文字列リテラルの長さを計算します。","en":"Compute the length of a string literal, which behaves like `String#length`."},"template":"type LengthOfString<S extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<LengthOfString<''>, 0>>,\n Expect<Equal<LengthOfString<'kumiko'>, 6>>,\n Expect<Equal<LengthOfString<'reina'>, 5>>,\n Expect<Equal<LengthOfString<'Sound! Euphonium'>, 16>>,\n]\n"},{"no":300,"difficulty":"hard","path":"00300-hard-string-to-number","info":{"en":{"difficulty":"hard","title":"String to Number","tags":["template-literal"],"author":{"github":"g-plane","name":"Pig Fang"}}},"readme":{"ja":"`Number.parseInt`のように、文字列リテラルを数値に変換する型を実装します。","en":"Convert a string literal to a number, which behaves like `Number.parseInt`."},"template":"type ToNumber<S extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<ToNumber<'0'>, 0>>,\n Expect<Equal<ToNumber<'5'>, 5>>,\n Expect<Equal<ToNumber<'12'>, 12>>,\n Expect<Equal<ToNumber<'27'>, 27>>,\n]\n"},{"no":399,"difficulty":"hard","path":"00399-hard-tuple-filter","info":{"en":{"difficulty":"hard","title":"Tuple Filter","tags":["tuple","infer"],"author":{"github":"softoika","name":"Ryo Hanafusa"}}},"readme":{"ja":"タプル`T`から指定された型`F`をフィルタリングする`FilterOut<T, F>`を実装します。\n\n例えば、\n\n```ts\ntype Filtered = FilterOut<[1, 2, null, 3], null>; // [1, 2, 3]\n```","en":"Implement a type `FilterOut<T, F>` that filters out items of the given type `F` from the tuple `T`.\n\nFor example,\n```ts\ntype Filtered = FilterOut<[1, 2, null, 3], null> // [1, 2, 3]\n```"},"template":"type FilterOut<T extends any[], F> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<FilterOut<[], never>, []>>,\n Expect<Equal<FilterOut<[never], never>, []>>,\n Expect<Equal<FilterOut<['a', never], never>, ['a']>>,\n Expect<Equal<FilterOut<[1, never, 'a'], never>, [1, 'a']>>,\n Expect<Equal<FilterOut<[never, 1, 'a', undefined, false, null], never | null | undefined>, [1, 'a', false]>>,\n Expect<Equal<FilterOut<[number | null | undefined, never], never | null | undefined>, [number | null | undefined]>>,\n]\n"},{"no":459,"difficulty":"medium","path":"00459-medium-flatten","info":{"en":{"difficulty":"medium","title":"Flatten","tags":["array"],"author":{"github":"chbro","name":"zhouyiming"}}},"readme":{"zh-CN":"在这个挑战中,你需要写一个接受数组的类型,并且返回扁平化的数组类型。\n\n例如:\n\n```ts\ntype flatten = Flatten<[1, 2, [3, 4], [[[5]]]]> // [1, 2, 3, 4, 5]\n```","ja":"この課題では、受け取った配列をフラット化した型を出力する型を書く必要があります。\n\n例えば:\n\n```ts\ntype flatten = Flatten<[1, 2, [3, 4], [[[5]]]> // [1, 2, 3, 4, 5]\n```","en":"In this challenge, you would need to write a type that takes an array and emitted the flatten array type.\n\nFor example:\n\n```ts\ntype flatten = Flatten<[1, 2, [3, 4], [[[5]]]]> // [1, 2, 3, 4, 5]\n```"},"template":"type Flatten = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Flatten<[]>, []>>,\n Expect<Equal<Flatten<[1, 2, 3, 4]>, [1, 2, 3, 4]>>,\n Expect<Equal<Flatten<[1, [2]]>, [1, 2]>>,\n Expect<Equal<Flatten<[1, 2, [3, 4], [[[5]]]]>, [1, 2, 3, 4, 5]>>,\n Expect<Equal<Flatten<[{ foo: 'bar'; 2: 10 }, 'foobar']>, [{ foo: 'bar'; 2: 10 }, 'foobar']>>,\n]\n"},{"no":462,"difficulty":"extreme","path":"00462-extreme-currying-2","info":{"zh-CN":{"title":"柯里化 2"},"en":{"difficulty":"extreme","title":"Currying 2","author":{"github":"hubvue","name":"Kim"},"related":["17"]}},"readme":{"zh-CN":"[Currying](https://en.wikipedia.org/wiki/Currying) 是一种将带有多个参数的函数转换为每个带有一个参数的函数序列的技术。\n\n但是在前端的日常开发中,柯里化函数参数个数动态化却是非常常见的,例如 `Function.bind(this, [...params])`\n\n```ts\nconst func = (a: number, b: number, c: number) => {\n return a + b + c\n}\n\nconst bindFunc = func(null, 1, 2)\n\nconst result = bindFunc(3) // result: 6\n```\n\n因此,在 `柯里化` 的基础上,我们更需要的是 `动态参数化的柯里化函数`\n\n```ts\nconst add = (a: number, b: number, c: number) => a + b + c\nconst three = add(1, 1, 1) \n\nconst curriedAdd = DynamicParamsCurrying(add)\nconst six = curriedAdd(1, 2, 3)\nconst seven = curriedAdd(1, 2)(4)\nconst eight = curriedAdd(2)(3)(4)\n```\n\n传递给 `DynamicParamsCurrying` 的函数可能有多个参数,您需要实现它的类型。\n\n在此挑战中,curriedAdd函数每次可接受最少一个参数,但是所有参数个数总和及类型与原函数相同。分配完所有参数后,它应返回其结果。","en":"[Currying](https://en.wikipedia.org/wiki/Currying) is the technique of converting a function that takes multiple arguments into a sequence of functions that each take a single argument.\n\nBut in our daily life, currying dynamic arguments is also commonly used, for example, the `Function.bind(this, [...params])` API.\n\n```ts\nconst func = (a: number, b: number, c: number) => {\n return a + b + c\n}\n\nconst bindFunc = func(null, 1, 2)\n\nconst result = bindFunc(3) // result: 6\n```\n\nThus, based on `Currying 1`, we would need to have the dynamic argument version:\n\n```ts\nconst add = (a: number, b: number, c: number) => a + b + c\nconst three = add(1, 1, 1) \n\nconst curriedAdd = DynamicParamsCurrying(add)\nconst six = curriedAdd(1, 2, 3)\nconst seven = curriedAdd(1, 2)(4)\nconst eight = curriedAdd(2)(3)(4)\n```\n\nIn this challenge, `DynamicParamsCurrying` may take a function with zero to multiple arguments, you need to correctly type it. The returned function may accept at least one argument. When all the arguments as satisfied, it should yield the return type of the original function correctly."},"template":"declare function DynamicParamsCurrying(fn: any): any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nconst curried1 = DynamicParamsCurrying((a: string, b: number, c: boolean) => true)\nconst curried2 = DynamicParamsCurrying((a: string, b: number, c: boolean, d: boolean, e: boolean, f: string, g: boolean) => true)\n\nconst curried1Return1 = curried1('123')(123)(true)\nconst curried1Return2 = curried1('123', 123)(false)\nconst curried1Return3 = curried1('123', 123, true)\n\nconst curried2Return1 = curried2('123')(123)(true)(false)(true)('123')(false)\nconst curried2Return2 = curried2('123', 123)(true, false)(true, '123')(false)\nconst curried2Return3 = curried2('123', 123)(true)(false)(true, '123', false)\nconst curried2Return4 = curried2('123', 123, true)(false, true, '123')(false)\nconst curried2Return5 = curried2('123', 123, true)(false)(true)('123')(false)\nconst curried2Return6 = curried2('123', 123, true, false)(true, '123', false)\nconst curried2Return7 = curried2('123', 123, true, false, true)('123', false)\nconst curried2Return8 = curried2('123', 123, true, false, true)('123')(false)\nconst curried2Return9 = curried2('123', 123, true, false, true, '123')(false)\nconst curried2Return10 = curried2('123', 123, true, false, true, '123', false)\n\ntype cases = [\n Expect<Equal< typeof curried1Return1, boolean>>,\n Expect<Equal< typeof curried1Return2, boolean>>,\n Expect<Equal< typeof curried1Return3, boolean>>,\n\n Expect<Equal< typeof curried2Return1, boolean>>,\n Expect<Equal< typeof curried2Return2, boolean>>,\n Expect<Equal< typeof curried2Return3, boolean>>,\n Expect<Equal< typeof curried2Return4, boolean>>,\n Expect<Equal< typeof curried2Return5, boolean>>,\n Expect<Equal< typeof curried2Return6, boolean>>,\n Expect<Equal< typeof curried2Return7, boolean>>,\n Expect<Equal< typeof curried2Return8, boolean>>,\n Expect<Equal< typeof curried2Return9, boolean>>,\n Expect<Equal< typeof curried2Return10, boolean>>,\n]\n"},{"no":472,"difficulty":"hard","path":"00472-hard-tuple-to-enum-object","info":{"en":{"difficulty":"hard","title":"Tuple to Enum Object","tags":["tuple","template-literal"],"author":{"github":"softoika","name":"Ryo Hanafusa"},"related":["10","11","730","3188"]}},"readme":{"ja":"enum は TypeScript 独自の文法です(JavaScript にはありません)。そのため、以下の形式にトランスパイルされます。\n\n```js\nlet OperatingSystem;\n(function (OperatingSystem) {\n OperatingSystem[(OperatingSystem['MacOS'] = 0)] = 'MacOS';\n OperatingSystem[(OperatingSystem['Windows'] = 1)] = 'Windows';\n OperatingSystem[(OperatingSystem['Linux'] = 2)] = 'Linux';\n})(OperatingSystem || (OperatingSystem = {}));\n```\n\nこの問題では、文字列のタプルを enum と同じようなオブジェクトに変換する型を実装します。\nさらに、enum のプロパティはパスカルケースであることが好ましいです。\n\n```ts\nEnum<[\"macOS\", \"Windows\", \"Linux\"]>\n// -> { readonly MacOS: \"macOS\", readonly Windows: \"Windows\", readonly Linux: \"Linux\" }\n```\n\n第 2 引数に`true`が与えられた場合、値は数値リテラルとなります。\n\n```ts\nEnum<[\"macOS\", \"Windows\", \"Linux\"], true>\n// -> { readonly MacOS: 0, readonly Windows: 1, readonly Linux: 2 }\n```","en":"The enum is an original syntax of TypeScript (it does not exist in JavaScript). So it is converted to like the following form as a result of transpilation:\n```js\nlet OperatingSystem;\n(function (OperatingSystem) {\n OperatingSystem[OperatingSystem[\"MacOS\"] = 0] = \"MacOS\";\n OperatingSystem[OperatingSystem[\"Windows\"] = 1] = \"Windows\";\n OperatingSystem[OperatingSystem[\"Linux\"] = 2] = \"Linux\";\n})(OperatingSystem || (OperatingSystem = {}));\n```\nIn this question, the type should convert a given string tuple to an object that behaves like an enum.\nMoreover, the property of an enum is preferably a pascal case.\n```ts\nEnum<[\"macOS\", \"Windows\", \"Linux\"]>\n// -> { readonly MacOS: \"macOS\", readonly Windows: \"Windows\", readonly Linux: \"Linux\" }\n```\nIf `true` is given in the second argument, the value should be a number literal.\n```ts\nEnum<[\"macOS\", \"Windows\", \"Linux\"], true>\n// -> { readonly MacOS: 0, readonly Windows: 1, readonly Linux: 2 }\n```"},"template":"type Enum<T extends readonly string[], N extends boolean = false> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nconst OperatingSystem = ['macOS', 'Windows', 'Linux'] as const\nconst Command = ['echo', 'grep', 'sed', 'awk', 'cut', 'uniq', 'head', 'tail', 'xargs', 'shift'] as const\n\ntype cases = [\n Expect<Equal<Enum<[]>, {}>>,\n Expect<Equal<\n Enum<typeof OperatingSystem>,\n {\n readonly MacOS: 'macOS'\n readonly Windows: 'Windows'\n readonly Linux: 'Linux'\n }\n >>,\n Expect<Equal<\n Enum<typeof OperatingSystem, true>,\n {\n readonly MacOS: 0\n readonly Windows: 1\n readonly Linux: 2\n }\n >>,\n Expect<Equal<\n Enum<typeof Command>,\n {\n readonly Echo: 'echo'\n readonly Grep: 'grep'\n readonly Sed: 'sed'\n readonly Awk: 'awk'\n readonly Cut: 'cut'\n readonly Uniq: 'uniq'\n readonly Head: 'head'\n readonly Tail: 'tail'\n readonly Xargs: 'xargs'\n readonly Shift: 'shift'\n }\n >>,\n Expect<Equal<\n Enum<typeof Command, true>,\n {\n readonly Echo: 0\n readonly Grep: 1\n readonly Sed: 2\n readonly Awk: 3\n readonly Cut: 4\n readonly Uniq: 5\n readonly Head: 6\n readonly Tail: 7\n readonly Xargs: 8\n readonly Shift: 9\n }\n >>,\n]\n"},{"no":476,"difficulty":"extreme","path":"00476-extreme-sum","info":{"en":{"difficulty":"extreme","title":"Sum","tags":["math","template-literal"],"author":{"github":"uid11","name":null}}},"readme":{"en":"Implement a type `Sum<A, B>` that summing two non-negative integers and returns the sum as a string. Numbers can be specified as a string, number, or bigint.\n\nFor example,\n\n```ts\ntype T0 = Sum<2, 3> // '5'\ntype T1 = Sum<'13', '21'> // '34'\ntype T2 = Sum<'328', 7> // '335'\ntype T3 = Sum<1_000_000_000_000n, '123'> // '1000000000123'\n```"},"template":"type Sum<A extends string | number | bigint, B extends string | number | bigint> = string\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Sum<2, 3>, '5'>>,\n Expect<Equal<Sum<'13', '21'>, '34'>>,\n Expect<Equal<Sum<'328', 7>, '335'>>,\n Expect<Equal<Sum<1_000_000_000_000n, '123'>, '1000000000123'>>,\n Expect<Equal<Sum<9999, 1>, '10000'>>,\n Expect<Equal<Sum<4325234, '39532'>, '4364766'>>,\n Expect<Equal<Sum<728, 0>, '728'>>,\n Expect<Equal<Sum<'0', 213>, '213'>>,\n Expect<Equal<Sum<0, '0'>, '0'>>,\n]\n"},{"no":517,"difficulty":"extreme","path":"00517-extreme-multiply","info":{"en":{"difficulty":"extreme","title":"Multiply","tags":["math","template-literal"],"related":["476"],"author":{"github":"uid11","name":null}}},"readme":{"en":"**This challenge continues from [476 - Sum](https://tsch.js.org/476), it is recommended that you finish that one first, and modify your code based on it to start this challenge.**\n\nImplement a type `Multiply<A, B>` that multiplies two non-negative integers and returns their product as a string. Numbers can be specified as string, number, or bigint.\n\nFor example,\n\n```ts\ntype T0 = Multiply<2, 3> // '6'\ntype T1 = Multiply<3, '5'> // '15'\ntype T2 = Multiply<'4', 10> // '40'\ntype T3 = Multiply<0, 16> // '0'\ntype T4 = Multiply<'13', '21'> // '273'\ntype T5 = Multiply<'43423', 321543n> // '13962361689'\n```"},"template":"type Multiply<A extends string | number | bigint, B extends string | number | bigint> = string\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Multiply<2, 3>, '6'>>,\n Expect<Equal<Multiply<3, '5'>, '15'>>,\n Expect<Equal<Multiply<'4', 10>, '40'>>,\n Expect<Equal<Multiply<0, 16>, '0'>>,\n Expect<Equal<Multiply<'13', '21'>, '273'>>,\n Expect<Equal<Multiply<'43423', 321543n>, '13962361689'>>,\n Expect<Equal<Multiply<9999, 1>, '9999'>>,\n Expect<Equal<Multiply<4325234, '39532'>, '170985150488'>>,\n Expect<Equal<Multiply<100_000n, '1'>, '100000'>>,\n Expect<Equal<Multiply<259, 9125385>, '2363474715'>>,\n Expect<Equal<Multiply<9, 99>, '891'>>,\n Expect<Equal<Multiply<315, '100'>, '31500'>>,\n Expect<Equal<Multiply<11n, 13n>, '143'>>,\n Expect<Equal<Multiply<728, 0>, '0'>>,\n Expect<Equal<Multiply<'0', 213>, '0'>>,\n Expect<Equal<Multiply<0, '0'>, '0'>>,\n]\n"},{"no":527,"difficulty":"medium","path":"00527-medium-append-to-object","info":{"en":{"difficulty":"medium","title":"Append to object","tags":["object-keys"],"author":{"github":"bre30kra69cs","name":"Andrey Krasovsky"}}},"readme":{"zh-CN":"实现一个为接口添加一个新字段的类型。该类型接收三个参数,返回带有新字段的接口类型。\n\n例如:\n\n```ts\ntype Test = { id: '1' }\ntype Result = AppendToObject<Test, 'value', 4> // expected to be { id: '1', value: 4 }\n```","ja":"インターフェースに新しいフィールドを追加する型を実装します。この型は、3 つの引数を受け取り、新しいフィールドを持つオブジェクトを出力しなければなりません。\n\n例えば、\n\n```ts\ntype Test = { id: '1' };\ntype Result = AppendToObject<Test, 'value', 4>; // expected to be { id: '1', value: 4 }\n```","en":"Implement a type that adds a new field to the interface. The type takes the three arguments. The output should be an object with the new field.\n\nFor example\n\n```ts\ntype Test = { id: '1' }\ntype Result = AppendToObject<Test, 'value', 4> // expected to be { id: '1', value: 4 }\n```"},"template":"type AppendToObject<T, U, V> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype test1 = {\n key: 'cat'\n value: 'green'\n}\n\ntype testExpect1 = {\n key: 'cat'\n value: 'green'\n home: boolean\n}\n\ntype test2 = {\n key: 'dog' | undefined\n value: 'white'\n sun: true\n}\n\ntype testExpect2 = {\n key: 'dog' | undefined\n value: 'white'\n sun: true\n home: 1\n}\n\ntype test3 = {\n key: 'cow'\n value: 'yellow'\n sun: false\n}\n\ntype testExpect3 = {\n key: 'cow'\n value: 'yellow'\n sun: false\n isMotherRussia: false | undefined\n}\n\ntype cases = [\n Expect<Equal<AppendToObject<test1, 'home', boolean>, testExpect1>>,\n Expect<Equal<AppendToObject<test2, 'home', 1>, testExpect2>>,\n Expect<Equal<AppendToObject<test3, 'isMotherRussia', false | undefined>, testExpect3>>,\n]\n"},{"no":529,"difficulty":"medium","path":"00529-medium-absolute","info":{"en":{"difficulty":"medium","title":"Absolute","tags":["math","template-literal"],"author":{"github":"bre30kra69cs","name":"Andrey Krasovsky"}}},"readme":{"zh-CN":"实现一个接收string,number或bigInt类型参数的`Absolute`类型,返回一个正数字符串。\n\n例如\n\n```ts\ntype Test = -100;\ntype Result = Absolute<Test>; // expected to be \"100\"\n```","ja":"srting, number または bigint を受け取り、正の数を出力する `Absolute` 型を実装します。\n\n例えば\n\n```ts\ntype Test = -100;\ntype Result = Absolute<Test>; // expected to be \"100\"\n```","en":"Implement the `Absolute` type. A type that take string, number or bigint. The output should be a positive number string\n\nFor example\n\n```ts\ntype Test = -100;\ntype Result = Absolute<Test>; // expected to be \"100\"\n```"},"template":"type Absolute<T extends number | string | bigint> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Absolute<0>, '0'>>,\n Expect<Equal<Absolute<-0>, '0'>>,\n Expect<Equal<Absolute<10>, '10'>>,\n Expect<Equal<Absolute<-5>, '5'>>,\n Expect<Equal<Absolute<'0'>, '0'>>,\n Expect<Equal<Absolute<'-0'>, '0'>>,\n Expect<Equal<Absolute<'10'>, '10'>>,\n Expect<Equal<Absolute<'-5'>, '5'>>,\n Expect<Equal<Absolute<-1_000_000n>, '1000000'>>,\n Expect<Equal<Absolute<9_999n>, '9999'>>,\n]\n"},{"no":531,"difficulty":"medium","path":"00531-medium-string-to-union","info":{"en":{"difficulty":"medium","title":"String to Union","tags":["union","string"],"author":{"github":"bre30kra69cs","name":"Andrey Krasovsky"}}},"readme":{"zh-CN":"实现一个将接收到的String参数转换为一个字母Union的类型。\n\n例如\n\n```ts\ntype Test = '123';\ntype Result = StringToUnion<Test>; // expected to be \"1\" | \"2\" | \"3\"\n```","ja":"受け取った文字列を Union 型に変換する型を実装します。\n\n例えば\n\n```ts\ntype Test = '123';\ntype Result = StringToUnion<Test>; // expected to be \"1\" | \"2\" | \"3\"\n```","en":"Implement the String to Union type. Type take string argument. The output should be a union of input letters\n\nFor example\n\n```ts\ntype Test = '123';\ntype Result = StringToUnion<Test>; // expected to be \"1\" | \"2\" | \"3\"\n```"},"template":"type StringToUnion<T extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<StringToUnion<''>, never>>,\n Expect<Equal<StringToUnion<'t'>, 't'>>,\n Expect<Equal<StringToUnion<'hello'>, 'h' | 'e' | 'l' | 'l' | 'o'>>,\n Expect<Equal<StringToUnion<'coronavirus'>, 'c' | 'o' | 'r' | 'o' | 'n' | 'a' | 'v' | 'i' | 'r' | 'u' | 's'>>,\n]\n"},{"no":533,"difficulty":"easy","path":"00533-easy-concat","info":{"en":{"difficulty":"easy","title":"Concat","tags":["array"],"author":{"github":"bre30kra69cs","name":"Andrey Krasovsky"},"related":["3057","3060"]}},"readme":{"zh-CN":"在类型系统里实现 JavaScript 内置的 `Array.concat` 方法,这个类型接受两个参数,返回的新数组类型应该按照输入参数从左到右的顺序合并为一个新的数组。\n\n举例,\n\n```ts\ntype Result = Concat<[1], [2]> // expected to be [1, 2]\n```","ja":"JavaScript の`Array.concat`関数を型システムに実装します。この型は 2 つの引数を受け取り、受け取ったイテレータの要素を順に含む新しい配列を返します。\n\n例えば\n\n```ts\ntype Result = Concat<[1], [2]>; // expected to be [1, 2]\n```","ko":"JavaScript의 `Array.concat` 함수를 타입 시스템에서 구현하세요. 타입은 두 인수를 받고, 인수를 왼쪽부터 concat한 새로운 배열을 반환해야 합니다.\n\n예시:\n\n```ts\ntype Result = Concat<[1], [2]> // expected to be [1, 2]\n```","en":"Implement the JavaScript `Array.concat` function in the type system. A type takes the two arguments. The output should be a new array that includes inputs in ltr order\n\nFor example\n\n```ts\ntype Result = Concat<[1], [2]> // expected to be [1, 2]\n```"},"template":"type Concat<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Concat<[], []>, []>>,\n Expect<Equal<Concat<[], [1]>, [1]>>,\n Expect<Equal<Concat<[1, 2], [3, 4]>, [1, 2, 3, 4]>>,\n Expect<Equal<Concat<['1', 2, '3'], [false, boolean, '4']>, ['1', 2, '3', false, boolean, '4']>>,\n]\n"},{"no":545,"difficulty":"hard","path":"00545-hard-printf","info":{"en":{"difficulty":"hard","title":"printf","tags":["template-literal"],"author":{"github":"Bestmain-YS","name":null}}},"readme":{"ja":"汎用的な`Format<T extends string>`を実装します。\n\n例えば、\n\n```ts\ntype FormatCase1 = Format<'%sabc'>; // FormatCase1 : string => string\ntype FormatCase2 = Format<'%s%dabc'>; // FormatCase2 : string => number => string\ntype FormatCase3 = Format<'sdabc'>; // FormatCase3 : string\ntype FormatCase4 = Format<'sd%abc'>; // FormatCase4 : string\n```","en":"Implement `Format<T extends string>` generic.\n\nFor example,\n\n```ts\ntype FormatCase1 = Format<\"%sabc\"> // FormatCase1 : string => string\ntype FormatCase2 = Format<\"%s%dabc\"> // FormatCase2 : string => number => string\ntype FormatCase3 = Format<\"sdabc\"> // FormatCase3 : string\ntype FormatCase4 = Format<\"sd%abc\"> // FormatCase4 : string\n```"},"template":"type Format<T extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Format<'abc'>, string>>,\n Expect<Equal<Format<'a%sbc'>, (s1: string) => string>>,\n Expect<Equal<Format<'a%dbc'>, (d1: number) => string>>,\n Expect<Equal<Format<'a%dbc%s'>, (d1: number) => (s1: string) => string>>,\n]\n"},{"no":553,"difficulty":"hard","path":"00553-hard-deep-object-to-unique","info":{"en":{"difficulty":"hard","title":"Deep object to unique","tags":["deep"],"author":{"github":"uid11","name":null}}},"readme":{"ja":"TypeScript は構造的型システムを持っていますが、場合によっては(公称型システムのように)あらかじめ定義されたユニークなオブジェクトだけを受け入れ、required なフィールドを持つオブジェクトは受け入れないようにしたいこともあるでしょう。\n\n引数にオブジェクトを受け取り、引数に含まれる全てのオブジェクトの文字列と数値のキー、およびこれらのキーの値のプロパティーを保持しながら、引数のオブジェクトとそれに含まれるネストしたオブジェクト全てをユニークにする型を実装します。\n\n元の型と実装した型のアウトプットの型は相互に代入可能でなければなりませんが、同一の型であってはいけません。\n\n例えば、\n\n```ts\nimport { Equal } from '@type-challenges/utils';\n\ntype Foo = { foo: 2; bar: { 0: 1 }; baz: { 0: 1 } };\n\ntype UniqFoo = DeepObjectToUniq<Foo>;\n\ndeclare let foo: Foo;\ndeclare let uniqFoo: UniqFoo;\n\nuniqFoo = foo; // ok\nfoo = uniqFoo; // ok\n\ntype T0 = Equal<UniqFoo, Foo>; // false\ntype T1 = UniqFoo['foo']; // 2\ntype T2 = Equal<UniqFoo['bar'], UniqFoo['baz']>; // false\ntype T3 = UniqFoo['bar'][0]; // 1\ntype T4 = Equal<keyof Foo & string, keyof UniqFoo & string>; // true\n```","en":"TypeScript has structural type system, but sometimes you want a function to accept only some previously well-defined unique objects (as in the nominal type system), and not any objects that have the required fields.\n\nCreate a type that takes an object and makes it and all deeply nested objects in it unique, while preserving the string and numeric keys of all objects, and the values of all properties on these keys.\n\nThe original type and the resulting unique type must be mutually assignable, but not identical. \n\nFor example,\n\n```ts\nimport { Equal } from \"@type-challenges/utils\"\n\ntype Foo = { foo: 2; bar: { 0: 1 }; baz: { 0: 1 } }\n\ntype UniqFoo = DeepObjectToUniq<Foo>\n\ndeclare let foo: Foo\ndeclare let uniqFoo: UniqFoo\n\nuniqFoo = foo // ok\nfoo = uniqFoo // ok\n\ntype T0 = Equal<UniqFoo, Foo> // false\ntype T1 = UniqFoo[\"foo\"] // 2\ntype T2 = Equal<UniqFoo[\"bar\"], UniqFoo[\"baz\"]> // false\ntype T3 = UniqFoo[\"bar\"][0] // 1\ntype T4 = Equal<keyof Foo & string, keyof UniqFoo & string> // true\n```"},"template":"type DeepObjectToUniq<O extends object> = any\n","tests":"import type { Equal, IsFalse, IsTrue } from '@type-challenges/utils'\n\ntype Quz = { quz: 4 }\n\ntype Foo = { foo: 2; baz: Quz; bar: Quz }\ntype Bar = { foo: 2; baz: Quz; bar: Quz & { quzz?: 0 } }\n\ntype UniqFoo = DeepObjectToUniq<Foo>\ntype UniqBar = DeepObjectToUniq<Bar>\n\ndeclare let foo: Foo\ndeclare let uniqFoo: UniqFoo\n\nuniqFoo = foo\nfoo = uniqFoo\n\ntype cases = [\n IsFalse<Equal<UniqFoo, Foo>>,\n IsTrue<Equal<UniqFoo['foo'], Foo['foo']>>,\n IsTrue<Equal<UniqFoo['bar']['quz'], Foo['bar']['quz']>>,\n IsFalse<Equal<UniqFoo['bar'], UniqFoo['baz']>>,\n IsFalse<Equal<UniqBar['baz'], UniqFoo['baz']>>,\n IsTrue<Equal<keyof UniqBar['baz'], keyof UniqFoo['baz']>>,\n IsTrue<Equal<keyof Foo, keyof UniqFoo & string>>,\n]\n"},{"no":599,"difficulty":"medium","path":"00599-medium-merge","info":{"en":{"difficulty":"medium","title":"Merge","tags":["object"],"author":{"github":"ZYSzys","name":"ZYSzys"}}},"readme":{"zh-CN":"将两个类型合并成一个类型,第二个类型的键会覆盖第一个类型的键。\n\n例如\n\n```ts\ntype foo = {\n name: string;\n age: string;\n}\n\ntype coo = {\n age: number;\n sex: string\n}\n\ntype Result = Merge<foo,coo>; // expected to be {name: string, age: number, sex: string}\n```","ja":"2 つの型をマージして新しい型を作ります。2 つ目に指定した型のキーは 1 つ目の型のキーを上書きします。\n\n例えば\n\n```ts\ntype foo = {\n name: string;\n age: string;\n}\ntype coo = {\n age: number;\n sex: string\n}\n\ntype Result = Merge<foo,coo>; // expected to be {name: string, age: number, sex: string}\n```","en":"Merge two types into a new type. Keys of the second type overrides keys of the first type.\n\nFor example\n\n```ts\ntype foo = {\n name: string;\n age: string;\n}\ntype coo = {\n age: number;\n sex: string\n}\n\ntype Result = Merge<foo,coo>; // expected to be {name: string, age: number, sex: string}\n```"},"template":"type Merge<F, S> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype Foo = {\n a: number\n b: string\n}\ntype Bar = {\n b: number\n c: boolean\n}\n\ntype cases = [\n Expect<Equal<Merge<Foo, Bar>, {\n a: number\n b: number\n c: boolean\n }>>,\n]\n"},{"no":612,"difficulty":"medium","path":"00612-medium-kebabcase","info":{"en":{"difficulty":"medium","title":"KebabCase","tags":["template-literal"],"author":{"github":"johnsoncodehk","name":"Johnson Chu"},"related":["114"]}},"readme":{"en":"`FooBarBaz` -> `foo-bar-baz`"},"template":"type KebabCase<S> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<KebabCase<'FooBarBaz'>, 'foo-bar-baz'>>,\n Expect<Equal<KebabCase<'fooBarBaz'>, 'foo-bar-baz'>>,\n Expect<Equal<KebabCase<'foo-bar'>, 'foo-bar'>>,\n Expect<Equal<KebabCase<'foo_bar'>, 'foo_bar'>>,\n Expect<Equal<KebabCase<'Foo-Bar'>, 'foo--bar'>>,\n Expect<Equal<KebabCase<'ABC'>, 'a-b-c'>>,\n Expect<Equal<KebabCase<'-'>, '-'>>,\n Expect<Equal<KebabCase<''>, ''>>,\n Expect<Equal<KebabCase<'😎'>, '😎'>>,\n]\n"},{"no":645,"difficulty":"medium","path":"00645-medium-diff","info":{"en":{"difficulty":"medium","title":"Diff","tags":["object"],"author":{"github":"ZYSzys","name":"ZYSzys"}}},"readme":{"zh-CN":"获取两个接口类型中的差值属性。\n\n```ts\ntype Foo = {\n a: string;\n b: number;\n}\ntype Bar = {\n a: string;\n c: boolean\n}\n\ntype Result1 = Diff<Foo,Bar> // { b: number, c: boolean }\ntype Result2 = Diff<Bar,Foo> // { b: number, c: boolean }\n\n```","en":"Get an `Object` that is the difference between `O` & `O1`"},"template":"type Diff<O, O1> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype Foo = {\n name: string\n age: string\n}\ntype Bar = {\n name: string\n age: string\n gender: number\n}\ntype Coo = {\n name: string\n gender: number\n}\n\ntype cases = [\n Expect<Equal<Diff<Foo, Bar>, { gender: number }>>,\n Expect<Equal<Diff<Bar, Foo>, { gender: number }>>,\n Expect<Equal<Diff<Foo, Coo>, { age: string; gender: number }>>,\n Expect<Equal<Diff<Coo, Foo>, { age: string; gender: number }>>,\n]\n"},{"no":651,"difficulty":"hard","path":"00651-hard-length-of-string-2","info":{"en":{"difficulty":"hard","title":"Length of String 2","tags":["template-literal"],"related":["298"],"author":{"github":"uid11","name":null}}},"readme":{"ja":"テンプレート文字列の長さを計算する`LengthOfString<S>`を実装します。([298 - Length of String](https://tsch.js.org/298)と同じような型):\n\n```ts\ntype T0 = LengthOfString<'foo'>; // 3\n```\n\nこの課題で実装する型は、数百文字の長さの文字列をサポートしなければなりません(通常の再帰的な文字列長の計算は、TS の再帰的な関数呼び出しの深さによって制限されています、つまり、45 文字程度までの文字列をサポートしています)。","en":"Implement a type `LengthOfString<S>` that calculates the length of the template string (as in [298 - Length of String](https://tsch.js.org/298)):\n\n```ts\ntype T0 = LengthOfString<\"foo\"> // 3\n```\n\nThe type must support strings several hundred characters long (the usual recursive calculation of the string length is limited by the depth of recursive function calls in TS, that is, it supports strings up to about 45 characters long)."},"template":"type LengthOfString<S extends string> = number\n","tests":"import type { Equal, IsTrue } from '@type-challenges/utils'\n\ntype cases = [\n IsTrue<Equal<LengthOfString<''>, 0>>,\n IsTrue<Equal<LengthOfString<'1'>, 1>>,\n IsTrue<Equal<LengthOfString<'12'>, 2>>,\n IsTrue<Equal<LengthOfString<'123'>, 3>>,\n IsTrue<Equal<LengthOfString<'1234'>, 4>>,\n IsTrue<Equal<LengthOfString<'12345'>, 5>>,\n IsTrue<Equal<LengthOfString<'123456'>, 6>>,\n IsTrue<Equal<LengthOfString<'1234567'>, 7>>,\n IsTrue<Equal<LengthOfString<'12345678'>, 8>>,\n IsTrue<Equal<LengthOfString<'123456789'>, 9>>,\n IsTrue<Equal<LengthOfString<'1234567890'>, 10>>,\n IsTrue<Equal<LengthOfString<'12345678901'>, 11>>,\n IsTrue<Equal<LengthOfString<'123456789012'>, 12>>,\n IsTrue<Equal<LengthOfString<'1234567890123'>, 13>>,\n IsTrue<Equal<LengthOfString<'12345678901234'>, 14>>,\n IsTrue<Equal<LengthOfString<'123456789012345'>, 15>>,\n IsTrue<Equal<LengthOfString<'1234567890123456'>, 16>>,\n IsTrue<Equal<LengthOfString<'12345678901234567'>, 17>>,\n IsTrue<Equal<LengthOfString<'123456789012345678'>, 18>>,\n IsTrue<Equal<LengthOfString<'1234567890123456789'>, 19>>,\n IsTrue<Equal<LengthOfString<'12345678901234567890'>, 20>>,\n IsTrue<Equal<LengthOfString<'123456789012345678901'>, 21>>,\n IsTrue<Equal<LengthOfString<'1234567890123456789012'>, 22>>,\n IsTrue<Equal<LengthOfString<'12345678901234567890123'>, 23>>,\n IsTrue<Equal<LengthOfString<'aaaaaaaaaaaaggggggggggggggggggggkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'>, 272>>,\n]\n"},{"no":697,"difficulty":"extreme","path":"00697-extreme-tag","info":{"en":{"difficulty":"extreme","title":"Tag","author":{"github":"uid11","name":null}}},"readme":{"en":"Despite the structural typing system in TypeScript, it is sometimes convenient to mark some types with tags, and so that these tags do not interfere with the ability to assign values of these types to each other.\n\nFor example, using tags, you can check that some value passes through the calls of the required functions, and in the correct order:\n```ts\nconst doA = <T extends string>(x: T) => {\n const result = x\n\n return result as Tag<typeof result, 'A'>\n}\n\nconst doB = <T extends string>(x: T) => {\n const result = x\n\n return result as Tag<typeof result, 'B'>\n};\n\nconst a = doA('foo')\nconst b = doB(a)\n\ntype Check0 = IsTrue<HasTags<typeof b, ['A', 'B']>>\n```\n\nWrite a function `Tag<B, T extends string>` that takes a type `B` other than `null` and `undefined` and returns a type labeled with the string literal type `T`.\n\nThe labeled types must be mutually assignable with the corresponding original types:\n```ts\ndeclare let x: string\ndeclare let y: Tag<string, 'A'>\n\nx = y = x\n```\n\nWhen tagging a type already marked with a tag, a new tag must be added to the end of the list of all tags of the type:\n```ts\ntype T0 = Tag<{ foo: string }, 'A'>\ntype T1 = Tag<T0, 'B'>\n\ntype Check1 = IsTrue<HasExactTags<T1, ['A', 'B']>>\n```\n\nAdd some functions to check for type tags.\n\n`GetTags<B>` retrieves a list of all tags of a type `B`:\n```ts\ntype T2 = Tag<number, 'C'>\n\ntype Check2 = IsTrue<Equal<GetTags<T2>, ['C']>>\n```\n\n`HasTag<B, T extends string>` checks if type `B` is tagged with tag `T` (and returns `true` or `false`):\n```ts\ntype T3 = Tag<0 | 1, 'D'>\n\ntype Check3 = IsTrue<HasTag<T3, 'D'>>\n```\n\n`HasTags<B, T extends readonly string[]>` checks if type `B` is tagged in succession with tags from tuple `T`:\n```ts\ntype T4 = Tag<Tag<Tag<{}, 'A'>, 'B'>, 'C'>\n\ntype Check4 = IsTrue<HasTags<T4, ['B', 'C']>>\n```\n\n`HasExactTags<B, T extends readonly string[]>` checks if the list of all tags of type `B` is exactly equal to the `T` tuple:\n```ts\ntype T5 = Tag<Tag<unknown, 'A'>, 'B'>\n\ntype Check5 = IsTrue<HasExactTags<T5, ['A', 'B']>>\n```\n\nFinally, add type `UnTag<B>`, which removes all tags from type `B`:\n```ts\ntype T6 = Tag<{ bar: number }, 'A'>\ntype T7 = UnTag<T6>\n\ntype Check6 = IsFalse<HasTag<T7, 'A'>>\n```"},"template":"type GetTags<B> = any\n\ntype Tag<B, T extends string> = any\n\ntype UnTag<B> = any\n\ntype HasTag<B, T extends string> = any\ntype HasTags<B, T extends readonly string[]> = any\ntype HasExactTags<B, T extends readonly string[]> = any\n","tests":"import type { Equal, Expect, IsTrue } from '@type-challenges/utils'\n\n/**\n * Tests of assignable of tagged variables.\n */\ninterface I {\n foo: string\n}\n\ndeclare let x0: I\ndeclare let x1: Tag<I, 'a'>\ndeclare let x2: Tag<I, 'b'>\ndeclare let x3: Tag<Tag<I, 'a'>, 'b'>\ndeclare let x4: Tag<Tag<I, 'b'>, 'a'>\ndeclare let x5: Tag<Tag<I, 'c'>, 'a'>\ndeclare let x6: Tag<Tag<I, 'c'>, 'b'>\ndeclare let x7: UnTag<Tag<Tag<I, 'c'>, 'b'>>\n\nx0 = x1 = x0 = x2 = x0 = x3 = x0 = x4 = x0 = x5 = x0 = x6 = x0 = x7 = x0\nx1 = x2 = x1 = x3 = x1 = x4 = x1 = x5 = x1 = x6 = x1 = x7 = x1\nx2 = x3 = x2 = x4 = x2 = x5 = x2 = x6 = x2 = x6 = x2\nx3 = x4 = x4 = x5 = x3 = x6 = x3 = x7 = x3\nx4 = x5 = x5 = x6 = x4 = x7 = x4\nx5 = x6 = x5 = x7 = x5\nx6 = x7 = x6\n\ndeclare let y0: string\ndeclare let y1: Tag<string, 'a'>\ndeclare let y2: Tag<string, 'b'>\ndeclare let y3: Tag<Tag<string, 'a'>, 'b'>\ndeclare let y4: Tag<Tag<string, 'b'>, 'a'>\ndeclare let y5: Tag<Tag<string, 'c'>, 'a'>\ndeclare let y6: Tag<Tag<string, 'c'>, 'b'>\ndeclare let y7: UnTag<Tag<Tag<string, 'c'>, 'b'>>\n\ny0 = y1 = y0 = y2 = y0 = y3 = y0 = y4 = y0 = y5 = y0 = y6 = y0 = y7 = y0\ny1 = y2 = y1 = y3 = y1 = y4 = y1 = y5 = y1 = y6 = y1 = y7 = y1\ny2 = y3 = y2 = y4 = y2 = y5 = y2 = y6 = y2 = y7 = y2\ny3 = y4 = y4 = y5 = y3 = y6 = y3 = y7 = y3\ny4 = y5 = y5 = y6 = y4 = y7 = y4\ny5 = y6 = y5 = y7 = y5\ny6 = y7 = y6\n\n// @ts-expect-error\nx0 = y0\n// @ts-expect-error\nx1 = y1\n// @ts-expect-error\nx2 = y2\n// @ts-expect-error\nx3 = y3\n// @ts-expect-error\nx4 = y4\n// @ts-expect-error\nx5 = y5\n// @ts-expect-error\nx6 = y6\n// @ts-expect-error\nx7 = y7\n\ndeclare const UNIQUE_SYMBOL: unique symbol\ntype US = typeof UNIQUE_SYMBOL\n\n/**\n * Tests of API (Tag, GetTags, Untag, HasTag, HasTags, HasExactTags).\n */\ntype cases = [\n /**\n * Tag.\n */\n IsTrue<Equal<Tag<null, 'foo'>, null>>,\n IsTrue<Equal<Tag<undefined, 'foo'>, undefined>>,\n IsTrue<Equal<'x', keyof Tag<{ x: 0 }, 'foo'> & string>>,\n\n /**\n * GetTags.\n */\n IsTrue<Equal<GetTags<null>, []>>,\n IsTrue<Equal<GetTags<any>, []>>,\n IsTrue<Equal<GetTags<undefined>, []>>,\n IsTrue<Equal<GetTags<Tag<any, 'foo'>>, ['foo']>>,\n IsTrue<Equal<GetTags<Tag<null | 1, 'foo'>>, ['foo']>>,\n IsTrue<Equal<GetTags<Tag<0, 'foo'> | 1>, []>>,\n IsTrue<Equal<GetTags<Tag<{}, 'foo'> | Tag<1, 'foo'>>, ['foo']>>,\n IsTrue<Equal<GetTags<Tag<string, 'foo'>>, ['foo']>>,\n IsTrue<Equal<GetTags<Tag<never, 'foo'>>, ['foo']>>,\n IsTrue<Equal<GetTags<Tag<Tag<string, 'foo'>, 'bar'>>, ['foo', 'bar']>>,\n IsTrue<\n Equal<\n GetTags<Tag<Tag<Tag<{}, 'foo'>, 'bar'>, 'baz'>>,\n ['foo', 'bar', 'baz']\n >\n >,\n\n /**\n * UnTag.\n */\n IsTrue<Equal<UnTag<null>, null>>,\n IsTrue<Equal<UnTag<undefined>, undefined>>,\n IsTrue<Equal<UnTag<Tag<{}, 'foo'>>, {}>>,\n IsTrue<Equal<UnTag<Tag<Tag<{ x: 0 }, 'foo'>, 'bar'>>, { x: 0 }>>,\n IsTrue<Equal<keyof UnTag<Tag<Tag<number, 'foo'>, 'bar'>>, keyof number>>,\n\n /**\n * HasTag.\n */\n Expect<Equal<HasTag<null, 'foo'>, false>>,\n Expect<Equal<HasTag<undefined, 'foo'>, false>>,\n Expect<Equal<HasTag<Tag<any, 'foo'>, 'foo'>, true>>,\n Expect<Equal<HasTag<Tag<1, 'foo'> | {}, 'foo'>, false>>,\n Expect<Equal<HasTag<Tag<{}, 'foo'>, 'foo'>, true>>,\n Expect<Equal<HasTag<Tag<0, 'foo'> | Tag<1, 'foo'>, 'foo'>, true>>,\n Expect<Equal<HasTag<Tag<0, 'foo'> | Tag<1, 'bar'>, 'foo'>, false>>,\n Expect<Equal<HasTag<Tag<Tag<{}, 'foo'>, 'bar'>, 'foo'>, true>>,\n Expect<Equal<HasTag<Tag<Tag<symbol, 'bar'>, 'foo'>, 'foo'>, true>>,\n Expect<Equal<HasTag<Tag<Tag<{}, 'bar'>, 'baz'>, 'foo'>, false>>,\n Expect<Equal<HasTag<Tag<true, 'foo'>, 'foo'>, true>>,\n Expect<Equal<HasTag<Tag<null, 'foo'>, 'foo'>, false>>,\n Expect<Equal<HasTag<Tag<Tag<undefined, 'foo'>, 'bar'>, 'bar'>, false>>,\n Expect<Equal<HasTag<Tag<Tag<false, 'foo'>, 'bar'>, 'foo'>, true>>,\n Expect<Equal<HasTag<Tag<Tag<never, 'bar'>, 'foo'>, 'foo'>, true>>,\n Expect<Equal<HasTag<Tag<{}, 'foo'>, 'foo'>, true>>,\n Expect<Equal<HasTag<Tag<{}, 'foo'>, 'bar'>, false>>,\n Expect<Equal<HasTag<{}, 'foo'>, false>>,\n\n /**\n * HasTags.\n */\n Expect<Equal<HasTags<null, ['foo']>, false>>,\n Expect<Equal<HasTags<undefined, ['foo']>, false>>,\n Expect<Equal<HasTags<Tag<any, 'bar'>, ['foo']>, false>>,\n Expect<Equal<HasTags<Tag<{}, 'bar'>, ['foo']>, false>>,\n Expect<Equal<HasTags<Tag<{}, 'foo'>, ['foo']>, true>>,\n Expect<Equal<HasTags<Tag<any, 'foo'>, ['foo']>, true>>,\n Expect<Equal<HasTags<Tag<{} | undefined, 'foo'>, ['foo']>, true>>,\n Expect<Equal<HasTags<Tag<Tag<string, 'foo'>, 'bar'>, ['foo', 'bar']>, true>>,\n Expect<Equal<HasTags<Tag<Tag<3n, 'foo'>, 'bar'>, ['foo', 'bar']>, true>>,\n Expect<Equal<HasTags<Tag<Tag<{}, 'bar'>, 'foo'>, ['foo', 'bar']>, false>>,\n Expect<Equal<HasTags<Tag<Tag<Tag<{}, 'baz'>, 'foo'>, 'bar'>, ['foo', 'bar']>, true>>,\n Expect<Equal<HasTags<Tag<Tag<Tag<symbol, 'baz'>, 'foo'>, 'bar'>, ['foo', 'bar']>, true>>,\n Expect<Equal<HasTags<Tag<Tag<Tag<{}, 'foo'>, 'bar'>, 'baz'>, ['foo', 'bar']>, true>>,\n Expect<Equal<HasTags<Tag<Tag<Tag<0, 'foo'>, 'bar'>, 'baz'>, ['foo', 'bar']>, true>>,\n Expect<Equal<HasTags<Tag<Tag<Tag<{}, 'foo'>, 'baz'>, 'bar'>, ['foo', 'bar']>, false>>,\n Expect<Equal<HasTags<Tag<Tag<unknown, 'foo'>, 'bar'>, ['foo', 'bar']>, true>>,\n\n /**\n * HasExactTags.\n */\n Expect<Equal<HasExactTags<0, []>, true>>,\n Expect<Equal<HasExactTags<null, []>, true>>,\n Expect<Equal<HasExactTags<undefined, []>, true>>,\n Expect<Equal<HasExactTags<Tag<number, 'foo'>, ['foo']>, true>>,\n Expect<Equal<HasExactTags<Tag<any, 'foo'>, ['bar']>, false>>,\n Expect<Equal<HasExactTags<Tag<Tag<any, 'foo'>, 'bar'>, ['foo', 'bar']>, true>>,\n Expect<Equal<HasExactTags<Tag<'', 'foo'>, ['foo']>, true>>,\n Expect<Equal<HasExactTags<Tag<US, 'foo'>, ['foo']>, true>>,\n Expect<Equal<HasExactTags<Tag<{}, 'foo'>, ['bar']>, false>>,\n Expect<Equal<HasExactTags<Tag<Tag<Tag<{}, 'foo'>, 'bar'>, 'baz'>, ['foo', 'bar']>, false>>,\n Expect<Equal<HasExactTags<Tag<Tag<Tag<{}, 'foo'>, 'bar'>, 'baz'>, ['foo', 'bar', 'baz']>, true>>,\n Expect<Equal<HasExactTags<Tag<Tag<void, 'foo'>, 'bar'>, ['foo', 'bar']>, true>>,\n]\n"},{"no":730,"difficulty":"hard","path":"00730-hard-union-to-tuple","info":{"en":{"difficulty":"hard","title":"Union to Tuple","tags":["union","tuple","infer"],"author":{"github":"suica","name":"Sg"},"related":["10","11","55","472","3188"]}},"readme":{"en":"Implement a type, `UnionToTuple`, that converts a union to a tuple.\n\nAs we know, union is an unordered structure, but tuple is an ordered, which implies that we are not supposed to preassume any order will be preserved between terms of one union, when unions are created or transformed. \n\nHence in this challenge, **any permutation of the elements in the output tuple is acceptable**.\n\nYour type should resolve to one of the following two types, but ***NOT*** a union of them!\n```ts\nUnionToTuple<1> // [1], and correct\nUnionToTuple<'any' | 'a'> // ['any','a'], and correct\n```\nor \n```ts\nUnionToTuple<'any' | 'a'> // ['a','any'], and correct\n```\nIt shouldn't be a union of all acceptable tuples...\n```ts\nUnionToTuple<'any' | 'a'> // ['a','any'] | ['any','a'], which is incorrect\n```\n\n\nAnd a union could collapes, which means some types could absorb (or be absorbed by) others and there is no way to prevent this absorption. See the following examples:\n```ts\nEqual<UnionToTuple<any | 'a'>, UnionToTuple<any>> // will always be a true\nEqual<UnionToTuple<unknown | 'a'>, UnionToTuple<unknown>> // will always be a true\nEqual<UnionToTuple<never | 'a'>, UnionToTuple<'a'>> // will always be a true\nEqual<UnionToTuple<'a' | 'a' | 'a'>, UnionToTuple<'a'>> // will always be a true\n```"},"template":"type UnionToTuple<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype ExtractValuesOfTuple<T extends any[]> = T[keyof T & number]\n\ntype cases = [\n Expect<Equal<UnionToTuple<'a' | 'b'>['length'], 2>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<'a' | 'b'>>, 'a' | 'b'>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<'a'>>, 'a'>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<any>>, any>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<undefined | void | 1>>, void | 1>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<any | 1>>, any | 1>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<any | 1>>, any>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<'d' | 'f' | 1 | never>>, 'f' | 'd' | 1>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<[{ a: 1 }] | 1>>, [{ a: 1 }] | 1>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<never>>, never>>,\n Expect<Equal<ExtractValuesOfTuple<UnionToTuple<'a' | 'b' | 'c' | 1 | 2 | 'd' | 'e' | 'f' | 'g'>>, 'f' | 'e' | 1 | 2 | 'g' | 'c' | 'd' | 'a' | 'b'>>,\n]\n"},{"no":734,"difficulty":"extreme","path":"00734-extreme-inclusive-range","info":{"en":{"difficulty":"extreme","title":"Inclusive Range","tags":["infer","array"],"author":{"github":"suica","name":"Sg"}}},"readme":{"en":"Recursion depth in type system is one of the limitations of TypeScript, the number is around 45. \n\n*We need to go deeper*. And we could go deeper.\n\nIn this challenge, you are given one lower boundary and one higher boundary, by which a range of natural numbers is inclusively sliced. You should develop a technique that enables you to do recursion deeper than the limitation, since both boundary vary from 0 to 200. \n\nNote that when `Lower > Higher`, output an empty tuple."},"template":"type InclusiveRange<Lower extends number, Higher extends number> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<InclusiveRange<200, 1>, []>>,\n Expect<Equal<InclusiveRange<10, 5>, []>>,\n Expect<Equal<InclusiveRange<5, 5>, [5]>>,\n Expect<Equal<InclusiveRange<0, 10>, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]>>,\n Expect<Equal<InclusiveRange<1, 200>, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200]>>,\n Expect<Equal<InclusiveRange<22, 146>, [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146]>>,\n]\n"},{"no":741,"difficulty":"extreme","path":"00741-extreme-sort","info":{"en":{"difficulty":"extreme","title":"Sort","tags":["infer","array"],"author":{"github":"suica","name":"Sg"}}},"readme":{"en":"In this challenge, you are required to sort natural number arrays in either ascend order or descent order.\n\nAscend order examples:\n```ts\nSort<[]> // []\nSort<[1]> // [1]\nSort<[2, 4, 7, 6, 6, 6, 5, 8, 9]> // [2, 4, 5, 6, 6, 6, 7, 8, 9]\n```\n\nThe `Sort` type should also accept a boolean type. When it is `true`, the sorted result should be in descent order. Some examples:\n\n```ts\nSort<[3, 2, 1], true> // [3, 2, 1]\nSort<[3, 2, 0, 1, 0, 0, 0], true> // [3, 2, 1, 0, 0, 0, 0]\n```\n\nExtra challenges:\n1. Support natural numbers with 15+ digits.\n2. Support float numbers."},"template":"type Sort = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Sort<[]>, []>>,\n Expect<Equal<Sort<[1]>, [1]>>,\n Expect<Equal<Sort<[2, 1]>, [1, 2]>>,\n Expect<Equal<Sort<[0, 0, 0]>, [0, 0, 0]>>,\n Expect<Equal<Sort<[1, 2, 3]>, [1, 2, 3]>>,\n Expect<Equal<Sort<[3, 2, 1]>, [1, 2, 3]>>,\n Expect<Equal<Sort<[3, 2, 1, 2]>, [1, 2, 2, 3]>>,\n Expect<Equal<Sort<[3, 2, 0, 1, 0, 0, 0]>, [0, 0, 0, 0, 1, 2, 3]>>,\n Expect<Equal<Sort<[2, 4, 7, 6, 6, 6, 5, 8, 9]>, [2, 4, 5, 6, 6, 6, 7, 8, 9]>>,\n Expect<Equal<Sort<[1, 1, 2, 1, 1, 1, 1, 1, 1]>, [1, 1, 1, 1, 1, 1, 1, 1, 2]>>,\n Expect<Equal<Sort<[], true>, []>>,\n Expect<Equal<Sort<[1], true>, [1]>>,\n Expect<Equal<Sort<[2, 1], true>, [2, 1]>>,\n Expect<Equal<Sort<[0, 0, 0], true>, [0, 0, 0]>>,\n Expect<Equal<Sort<[1, 2, 3], true>, [3, 2, 1]>>,\n Expect<Equal<Sort<[3, 2, 1], true>, [3, 2, 1]>>,\n Expect<Equal<Sort<[3, 2, 1, 2], true>, [3, 2, 2, 1]>>,\n Expect<Equal<Sort<[3, 2, 0, 1, 0, 0, 0], true>, [3, 2, 1, 0, 0, 0, 0]>>,\n Expect<Equal<Sort<[2, 4, 7, 6, 6, 6, 5, 8, 9], true>, [9, 8, 7, 6, 6, 6, 5, 4, 2]>>,\n]\n"},{"no":847,"difficulty":"hard","path":"00847-hard-string-join","info":{"en":{"difficulty":"hard","title":"String Join","author":{"github":"tl-matt-davis","name":"Matt Davis"}}},"readme":{"en":"Create a type-safe string join utility which can be used like so:\n\n```ts\nconst hyphenJoiner = join('-')\nconst result = hyphenJoiner('a', 'b', 'c'); // = 'a-b-c'\n```\n\nOr alternatively:\n```ts\njoin('#')('a', 'b', 'c') // = 'a#b#c'\n```\n\nWhen we pass an empty delimiter (i.e '') to join, we should concat the strings as they are, i.e: \n```ts\njoin('')('a', 'b', 'c') // = 'abc'\n```\n\nWhen only one item is passed, we should get back the original item (without any delimiter added):\n```ts\njoin('-')('a') // = 'a'\n```"},"template":"declare function join(delimiter: any): (...parts: any[]) => any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\n// Edge cases\nconst noCharsOutput = join('-')()\nconst oneCharOutput = join('-')('a')\nconst noDelimiterOutput = join('')('a', 'b', 'c')\n\n// Regular cases\nconst hyphenOutput = join('-')('a', 'b', 'c')\nconst hashOutput = join('#')('a', 'b', 'c')\nconst twoCharOutput = join('-')('a', 'b')\nconst longOutput = join('-')('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')\n\ntype cases = [\n Expect<Equal<typeof noCharsOutput, ''>>,\n Expect<Equal<typeof oneCharOutput, 'a'>>,\n Expect<Equal<typeof noDelimiterOutput, 'abc'>>,\n Expect<Equal<typeof twoCharOutput, 'a-b'>>,\n Expect<Equal<typeof hyphenOutput, 'a-b-c'>>,\n Expect<Equal<typeof hashOutput, 'a#b#c'>>,\n Expect<Equal<typeof longOutput, 'a-b-c-d-e-f-g-h'>>,\n]\n"},{"no":869,"difficulty":"extreme","path":"00869-extreme-distributeunions","info":{"en":{"difficulty":"extreme","title":"DistributeUnions","author":{"github":"gvergnaud","name":"Gabriel Vergnaud"}}},"readme":{"en":"Implement a type `Distribute Unions`, that turns a type of data structure containing union types into a union of\nall possible types of permitted data structures that don't contain any union. The data structure can be any\ncombination of objects and tuples on any level of nesting.\n\nFor example:\n\n```ts\ntype T1 = DistributeUnions<[1 | 2, 'a' | 'b']>\n// => [1, 'a'] | [2, 'a'] | [1, 'b'] | [2, 'b']\n\ntype T2 = DistributeUnions<{ type: 'a', value: number | string } | { type: 'b', value: boolean }>\n// => | { type 'a', value: number }\n// | { type 'a', value: string }\n// | { type 'b', value: boolean }\n\ntype T3 = DistributeUnions<[{ value: 'a' | 'b' }, { x: { y: 2 | 3 } }] | 17>\n// => | [{ value: 'a' }, { x: { y: 2 } }]\n// | [{ value: 'a' }, { x: { y: 3 } }]\n// | [{ value: 'b' }, { x: { y: 2 } }]\n// | [{ value: 'b' }, { x: { y: 3 } }]\n// | 17\n```\n\nFor context, this type can be very useful if you want to exclude a case on deep data structures:\n\n```ts\ntype ExcludeDeep<A, B> = Exclude<DistributeUnions<A>, B>\n\ntype T0 = ExcludeDeep<[{ value: 'a' | 'b' }, { x: { y: 2 | 3 } }] | 17, [{ value: 'a' }, any]>\n// => | [{ value: 'b' }, { x: { y: 2 } }]\n// | [{ value: 'b' }, { x: { y: 3 } }]\n// | 17\n```"},"template":"type DistributeUnions<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n // Already distributed unions should stay the same:\n Expect<Equal<DistributeUnions<1>, 1>>,\n Expect<Equal<DistributeUnions<string>, string>>,\n Expect<Equal<DistributeUnions<1 | 2>, 1 | 2>>,\n Expect<Equal<DistributeUnions<'b' | { type: 'a' } | [1]>, 'b' | { type: 'a' } | [1]>>,\n // tuples:\n Expect<Equal<DistributeUnions<[1 | 2, 3]>, [1, 3] | [2, 3]>>,\n Expect<Equal<DistributeUnions<[1 | 2, 'a' | 'b']>, [1, 'a'] | [1, 'b'] | [2, 'a'] | [2, 'b']>>,\n Expect<\n Equal<\n DistributeUnions<[1 | 2, 'a' | 'b', false | true]>,\n | [1, 'a', false]\n | [1, 'a', true]\n | [1, 'b', false]\n | [1, 'b', true]\n | [2, 'a', false]\n | [2, 'a', true]\n | [2, 'b', false]\n | [2, 'b', true]\n >\n >,\n // objects\n Expect<\n Equal<\n DistributeUnions<{ x: 'a' | 'b'; y: 'c' | 'd' }>,\n { x: 'a'; y: 'c' } | { x: 'a'; y: 'd' } | { x: 'b'; y: 'c' } | { x: 'b'; y: 'd' }\n >\n >,\n Expect<\n Equal<\n DistributeUnions<{ type: 'a'; value: number | string } | { type: 'b'; value: boolean }>,\n | { type: 'a'; value: string }\n | { type: 'a'; value: number }\n | { type: 'b'; value: false }\n | { type: 'b'; value: true }\n >\n >,\n Expect<\n Equal<\n DistributeUnions<\n | {\n type: 'a'\n option: { kind: 'none' } | { kind: 'some'; value: 'x' | 'y' }\n }\n | { type: 'b'; msg: string }\n >,\n | { type: 'b'; msg: string }\n | { type: 'a'; option: { kind: 'none' } }\n | { type: 'a'; option: { kind: 'some'; value: 'x' } }\n | { type: 'a'; option: { kind: 'some'; value: 'y' } }\n >\n >,\n // mixed structures:\n Expect<\n Equal<\n DistributeUnions<[false | true, { value: 'a' | 'b' }, { x: { y: 2 | 3 } }]>,\n | [false, { value: 'a' }, { x: { y: 2 } }]\n | [false, { value: 'a' }, { x: { y: 3 } }]\n | [false, { value: 'b' }, { x: { y: 2 } }]\n | [false, { value: 'b' }, { x: { y: 3 } }]\n | [true, { value: 'a' }, { x: { y: 2 } }]\n | [true, { value: 'a' }, { x: { y: 3 } }]\n | [true, { value: 'b' }, { x: { y: 2 } }]\n | [true, { value: 'b' }, { x: { y: 3 } }]\n >\n >,\n Expect<\n Equal<\n DistributeUnions<17 | [10 | { value: 'a' | 'b' }, { x: { y: 2 | 3 } }]>,\n | 17\n | [10, { x: { y: 2 } }]\n | [10, { x: { y: 3 } }]\n | [{ value: 'a' }, { x: { y: 2 } }]\n | [{ value: 'a' }, { x: { y: 3 } }]\n | [{ value: 'b' }, { x: { y: 2 } }]\n | [{ value: 'b' }, { x: { y: 3 } }]\n >\n >,\n]\n"},{"no":898,"difficulty":"easy","path":"00898-easy-includes","info":{"en":{"difficulty":"easy","title":"Includes","tags":["array"],"author":{"github":"kynefuk","name":null}}},"readme":{"zh-CN":"在类型系统里实现 JavaScript 的 `Array.includes` 方法,这个类型接受两个参数,返回的类型要么是 `true` 要么是 `false`。\n\n举例来说,\n\n```ts\ntype isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'> // expected to be `false`\n```","ja":"JavaScriptの`Array.include`関数を型システムに実装します。この型は、2 つの引数を受け取り、`true`や`false`を出力しなければなりません。\n\n例えば\n\n```ts\ntype isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'> // expected to be `false`\n```","ko":"JavaScript의 `Array.includes` 함수를 타입 시스템에서 구현하세요. 타입은 두 인수를 받고, `true` 또는 `false`를 반환해야 합니다.\n\n예시:\n\n```ts\ntype isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'> // expected to be `false`\n```","en":"Implement the JavaScript `Array.includes` function in the type system. A type takes the two arguments. The output should be a boolean `true` or `false`.\n\nFor example\n\n```ts\ntype isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'> // expected to be `false`\n```"},"template":"type Includes<T extends readonly any[], U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Kars'>, true>>,\n Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'>, false>>,\n Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 7>, true>>,\n Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 4>, false>>,\n Expect<Equal<Includes<[1, 2, 3], 2>, true>>,\n Expect<Equal<Includes<[1, 2, 3], 1>, true>>,\n Expect<Equal<Includes<[{}], { a: 'A' }>, false>>,\n Expect<Equal<Includes<[boolean, 2, 3, 5, 6, 7], false>, false>>,\n Expect<Equal<Includes<[true, 2, 3, 5, 6, 7], boolean>, false>>,\n Expect<Equal<Includes<[false, 2, 3, 5, 6, 7], false>, true>>,\n Expect<Equal<Includes<[{ a: 'A' }], { readonly a: 'A' }>, false>>,\n Expect<Equal<Includes<[{ readonly a: 'A' }], { a: 'A' }>, false>>,\n Expect<Equal<Includes<[1], 1 | 2>, false>>,\n Expect<Equal<Includes<[1 | 2], 1>, false>>,\n Expect<Equal<Includes<[null], undefined>, false>>,\n Expect<Equal<Includes<[undefined], null>, false>>,\n]\n"},{"no":925,"difficulty":"extreme","path":"00925-extreme-assert-array-index","info":{"en":{"difficulty":"extreme","title":"Assert Array Index","tags":["array"],"tsconfig":{"noUncheckedIndexedAccess":true},"author":{"github":"uid11","name":null}}},"readme":{"en":"Sometimes we want to use the good old `for`-loop with an index to traverse the array, but in this case TypeScript does not check in any way that we are accessing the elements of the array at its real index (not exceeding the length of the array), and that we are not using an arbitrary number as an index, or index from another array (for nested loops, for traversing matrices or graphs):\n```ts\nconst matrix = [\n [3, 4],\n [5, 6],\n [7, 8],\n];\n\n// This example contains no type errors when the noUncheckedIndexedAccess option is off.\nfor (let i = 0; i < matrix.length; i += 1) {\n const columns: number[] = matrix[i];\n\n for (let j = 0; j < columns.length; j += 1) {\n const current: number = columns[i]; // oops! i instead of j\n\n console.log(\n current.toFixed(), // TypeError: Cannot read property 'toFixed' of undefined\n );\n }\n}\n```\n\nYou can enable the [noUncheckedIndexedAccess](https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess) option (in `tsconfig.json`), but then each time you access an array element, you will need to check that this element exists, which is somewhat verbose and inconvenient, especially since in the case of such a `for`-traversal, we are sure that the index does not exceed the length of the array:\n```ts\nconst numbers = [5, 7];\n\nfor (let i = 0; i < numbers.length; i += 1) {\n const current = numbers[i];\n\n if (current !== undefined) {\n console.log(current.toFixed());\n }\n}\n```\n\nWrite an `assert`-function `assertArrayIndex(array, key)` that can be applied to any `array` (with an arbitrary unique string `key`, which is needed to distinguish arrays at the type level) to allow access to the elements of this array only by the index obtained from array by the special generic type `Index<typeof array>` (this functionality requires enabling the [noUncheckedIndexedAccess](https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess) option in `tsconfig.json`):\n```ts\nconst numbers = [5, 7];\n\nassertArrayIndex(numbers, 'numbers');\n\nfor (let i = 0 as Index<typeof numbers>; i < numbers.length; i += 1) {\n console.log(numbers[i].toFixed());\n}\n```\n\nWhen accessing by such an index, it must be guaranteed that an element in the array exists, and when accessing an array by any other indices, there is no such guarantee (the element may not exist):\n```ts\nconst matrix = [\n [3, 4],\n [5, 6],\n [7, 8],\n];\n\nassertArrayIndex(matrix, 'rows');\n\nlet sum = 0;\n\nfor (let i = 0 as Index<typeof matrix>; i < matrix.length; i += 1) {\n const columns: number[] = matrix[i];\n\n // @ts-expect-error: number | undefined in not assignable to number\n const x: number[] = matrix[0];\n\n assertArrayIndex(columns, 'columns');\n\n for (let j = 0 as Index<typeof columns>; j < columns.length; j += 1) {\n sum += columns[j];\n\n // @ts-expect-error: number | undefined in not assignable to number\n const y: number = columns[i];\n\n // @ts-expect-error: number | undefined in not assignable to number\n const z: number = columns[0];\n\n // @ts-expect-error: number[] | undefined in not assignable to number[]\n const u: number[] = matrix[j];\n }\n}\n```\n\nThe `assertArrayIndex` function cannot be called on tuples (since the accessing the elements is already well typed in them):\n```ts\nconst tuple = [5, 7] as const;\n\n// @ts-expect-error\nassertArrayIndex(tuple, 'tuple');\n```\n\n(Additional design considerations for the proposed API: [#925](https://github.com/type-challenges/type-challenges/issues/925#issuecomment-780889329).)"},"template":"function assertArrayIndex(array: readonly unknown[], key: string) {}\n\ntype Index<Array> = any\n","tests":"const matrix = [\n [3, 4],\n [5, 6],\n [7, 8],\n]\n\nassertArrayIndex(matrix, 'rows')\n\nlet sum = 0\n\nfor (let i = 0 as Index<typeof matrix>; i < matrix.length; i += 1) {\n const columns: number[] = matrix[i]\n\n // @ts-expect-error: number | undefined in not assignable to number\n const x: number[] = matrix[0]\n\n assertArrayIndex(columns, 'columns')\n\n for (let j = 0 as Index<typeof columns>; j < columns.length; j += 1) {\n sum += columns[j]\n\n // @ts-expect-error: number | undefined in not assignable to number\n const y: number = columns[i]\n\n // @ts-expect-error: number | undefined in not assignable to number\n const z: number = columns[0]\n\n // @ts-expect-error: number[] | undefined in not assignable to number[]\n const u: number[] = matrix[j]\n }\n}\n\nconst a: string[] = []\n\nassertArrayIndex(a, 'a')\n\nfor (let p = 0 as Index<typeof a>; p < a.length; p += 1) {\n const value: string = a[p]\n\n // @ts-expect-error: string | undefined is not assignable to string\n const z: string = a[2]\n}\n\na.push('qux')\n// @ts-expect-error: number is not assignable to string\na.push(3)\n\nfor (const value of a) {\n const other: string = value\n}\n\nconst b: number[] = []\n\nassertArrayIndex(b, 'b')\n\nfor (let p = 0 as Index<typeof a>; p < b.length; p += 1) {\n // @ts-expect-error: number | undefined is not assignable to string\n const value: string = b[p]\n}\n\nconst c: string[] = []\n\nassertArrayIndex(c, 'c')\n\nfor (let p = 0; p < c.length; p += 1) {\n // @ts-expect-error: string | undefined is not assignable to string\n let value: string = c[p]\n\n // @ts-expect-error: string | undefined is not assignable to string\n value = c[0 as Index<typeof a>]\n}\n\nconst d: readonly number[] = []\n\nassertArrayIndex(d, 'd')\n\nfor (let p = 0 as Index<typeof d>; p < d.length; p += 1) {\n const value: number = d[p]\n\n // @ts-expect-error: only permits reading\n d[2] = 3\n}\n\n// @ts-expect-error: push does not exist on readonly\nd.push(3)\n\nconst e: [number] = [0]\n\n// @ts-expect-error: [number] is not assignable to never\nassertArrayIndex(e, 'e')\n\nconst f: readonly [boolean] = [false]\n\n// @ts-expect-error: [boolean] is not assignable to never\nassertArrayIndex(f, 'f')\n\nconst tuple = [5, 7] as const\n\n// @ts-expect-error: readonly [5, 7] is not assignable to never\nassertArrayIndex(tuple, 'tuple')\n"},{"no":949,"difficulty":"medium","path":"00949-medium-anyof","info":{"en":{"difficulty":"medium","title":"AnyOf","tags":["array"],"author":{"github":"kynefuk","name":null}}},"readme":{"zh-CN":"在类型系统中实现类似于 Python 中 `any` 函数。类型接收一个数组,如果数组中任一个元素为真,则返回 `true`,否则返回 `fasle`。如果数组为空,返回 `false`。\n\n例如:\n\n```ts\ntype Sample1 = AnyOf<[1, '', false, [], {}]> // expected to be true.\ntype Sample2 = AnyOf<[0, '', false, [], {}]> // expected to be false.\n```","en":"Implement Python liked `any` function in the type system. A type takes the Array and returns `true` if any element of the Array is true. If the Array is empty, return `false`.\n\nFor example:\n\n```ts\ntype Sample1 = AnyOf<[1, '', false, [], {}]> // expected to be true.\ntype Sample2 = AnyOf<[0, '', false, [], {}]> // expected to be false.\n```"},"template":"type AnyOf<T extends readonly any[]> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<AnyOf<[1, 'test', true, [1], { name: 'test' }, { 1: 'test' }]>, true>>,\n Expect<Equal<AnyOf<[1, '', false, [], {}]>, true>>,\n Expect<Equal<AnyOf<[0, 'test', false, [], {}]>, true>>,\n Expect<Equal<AnyOf<[0, '', true, [], {}]>, true>>,\n Expect<Equal<AnyOf<[0, '', false, [1], {}]>, true>>,\n Expect<Equal<AnyOf<[0, '', false, [], { name: 'test' }]>, true>>,\n Expect<Equal<AnyOf<[0, '', false, [], { 1: 'test' }]>, true>>,\n Expect<Equal<AnyOf<[0, '', false, [], { name: 'test' }, { 1: 'test' }]>, true>>,\n Expect<Equal<AnyOf<[0, '', false, [], {}]>, false>>,\n Expect<Equal<AnyOf<[]>, false>>,\n]\n"},{"no":956,"difficulty":"hard","path":"00956-hard-deeppick","info":{"en":{"difficulty":"hard","title":"DeepPick","tags":["deep"],"author":{"github":"hiroyaiizuka","name":"hiroya iizuka"}}},"readme":{"en":"Implement a type DeepPick, that extends Utility types `Pick`.\nA type takes two arguments.\n\n\nFor example:\n\n```\n\ntype obj = {\n name: 'hoge', \n age: 20,\n friend: {\n name: 'fuga',\n age: 30,\n family: {\n name: 'baz', \n age: 1 \n }\n }\n}\n\ntype T1 = DeepPick<obj, 'name'> // { name : 'hoge' }\ntype T2 = DeepPick<obj, 'name' | 'friend.name'> // { name : 'hoge' } & { friend: { name: 'fuga' }}\ntype T3 = DeepPick<obj, 'name' | 'friend.name' | 'friend.family.name'> // { name : 'hoge' } & { friend: { name: 'fuga' }} & { friend: { family: { name: 'baz' }}}\n\n```"},"template":"type DeepPick = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype Obj = {\n a: number\n b: string\n c: boolean\n obj: {\n d: number\n e: string\n f: boolean\n obj2: {\n g: number\n h: string\n i: boolean\n }\n }\n obj3: {\n j: number\n k: string\n l: boolean\n }\n}\n\ntype cases = [\n Expect<Equal<DeepPick<Obj, ''>, unknown >>,\n Expect<Equal<DeepPick<Obj, 'a'>, { a: number }>>,\n Expect<Equal<DeepPick<Obj, 'a' | 'obj.e'>, { a: number } & { obj: { e: string } }>>,\n Expect<Equal<DeepPick<Obj, 'a' | 'obj.e' | 'obj.obj2.i'>, { a: number } & { obj: { e: string } } & { obj: { obj2: { i: boolean } } }>>,\n]\n"},{"no":1042,"difficulty":"medium","path":"01042-medium-isnever","info":{"en":{"difficulty":"medium","title":"IsNever","tags":["union","utils"],"author":{"github":"hiroyaiizuka","name":"hiroya iizuka"},"related":["1097","223","4484"]}},"readme":{"en":"Implement a type IsNever, which takes input type `T`.\nIf the type of resolves to `never`, return `true`, otherwise `false`.\n\nFor example:\n\n```ts\ntype A = IsNever<never> // expected to be true\ntype B = IsNever<undefined> // expected to be false\ntype C = IsNever<null> // expected to be false\ntype D = IsNever<[]> // expected to be false\ntype E = IsNever<number> // expected to be false\n```"},"template":"type IsNever = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<IsNever<never>, true>>,\n Expect<Equal<IsNever<never | string>, false>>,\n Expect<Equal<IsNever<''>, false>>,\n Expect<Equal<IsNever<undefined>, false>>,\n Expect<Equal<IsNever<null>, false>>,\n Expect<Equal<IsNever<[]>, false>>,\n Expect<Equal<IsNever<{}>, false>>,\n]\n"},{"no":1097,"difficulty":"medium","path":"01097-medium-isunion","info":{"en":{"difficulty":"medium","title":"IsUnion","author":{"github":"bencor","name":null},"related":["1042","223","4484"]}},"readme":{"en":"Implement a type `IsUnion`, which takes an input type `T` and returns whether `T` resolves to a union type.\n\nFor example:\n \n ```ts\n type case1 = IsUnion<string> // false\n type case2 = IsUnion<string|number> // true\n type case3 = IsUnion<[string|number]> // false\n ```"},"template":"type IsUnion<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<IsUnion<string>, false >>,\n Expect<Equal<IsUnion<string|number>, true >>,\n Expect<Equal<IsUnion<'a'|'b'|'c'|'d'>, true >>,\n Expect<Equal<IsUnion<undefined|null|void|''>, true >>,\n Expect<Equal<IsUnion<{ a: string }|{ a: number }>, true >>,\n Expect<Equal<IsUnion<{ a: string|number }>, false >>,\n Expect<Equal<IsUnion<[string|number]>, false >>,\n // Cases where T resolves to a non-union type.\n Expect<Equal<IsUnion<string|never>, false >>,\n Expect<Equal<IsUnion<string|unknown>, false >>,\n Expect<Equal<IsUnion<string|any>, false >>,\n Expect<Equal<IsUnion<string|'a'>, false >>,\n]\n"},{"no":1130,"difficulty":"medium","path":"01130-medium-replacekeys","info":{"en":{"difficulty":"medium","title":"ReplaceKeys","author":{"github":"lullabyjune","name":"贱贱"}}},"readme":{"en":"Implement a type ReplaceKeys, that replace keys in union types, if some type has not this key, just skip replacing,\nA type takes three arguments. \n\n\nFor example:\n\n```ts\ntype NodeA = {\n type: 'A'\n name: string\n flag: number\n}\n\ntype NodeB = {\n type: 'B'\n id: number\n flag: number\n}\n\ntype NodeC = {\n type: 'C'\n name: string\n flag: number\n}\n\n\ntype Nodes = NodeA | NodeB | NodeC\n\ntype ReplacedNodes = ReplaceKeys<Nodes, 'name' | 'flag', {name: number, flag: string}> // {type: 'A', name: number, flag: string} | {type: 'B', id: number, flag: string} | {type: 'C', name: number, flag: string} // would replace name from string to number, replace flag from number to string.\n\ntype ReplacedNotExistKeys = ReplaceKeys<Nodes, 'name', {aa: number}> // {type: 'A', name: never, flag: number} | NodeB | {type: 'C', name: never, flag: number} // would replace name to never\n```"},"template":"type ReplaceKeys<U, T, Y> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype NodeA = {\n type: 'A'\n name: string\n flag: number\n}\n\ntype NodeB = {\n type: 'B'\n id: number\n flag: number\n}\n\ntype NodeC = {\n type: 'C'\n name: string\n flag: number\n}\n\ntype ReplacedNodeA = {\n type: 'A'\n name: number\n flag: string\n}\n\ntype ReplacedNodeB = {\n type: 'B'\n id: number\n flag: string\n}\n\ntype ReplacedNodeC = {\n type: 'C'\n name: number\n flag: string\n}\n\ntype NoNameNodeA = {\n type: 'A'\n flag: number\n name: never\n}\n\ntype NoNameNodeC = {\n type: 'C'\n flag: number\n name: never\n}\n\ntype Nodes = NodeA | NodeB | NodeC\ntype ReplacedNodes = ReplacedNodeA | ReplacedNodeB | ReplacedNodeC\ntype NodesNoName = NoNameNodeA | NoNameNodeC | NodeB\n\ntype cases = [\n Expect<Equal<ReplaceKeys<Nodes, 'name' | 'flag', { name: number; flag: string }>, ReplacedNodes>>,\n Expect<Equal<ReplaceKeys<Nodes, 'name', { aa: number }>, NodesNoName>>,\n]\n"},{"no":1290,"difficulty":"hard","path":"01290-hard-pinia","info":{"en":{"difficulty":"hard","title":"Pinia","tags":["this","vue"],"author":{"github":"g-plane","name":"Pig Fang"}}},"readme":{"en":"Create a type-level function whose types is similar to [Pinia](https://github.com/posva/pinia) library. You don't need to implement function actually, just adding types.\n\n### Overview\n\nThis function receive only one parameter whose type is an object. The object contains 4 properties:\n\n- `id` - just a string (required)\n- `state` - a function which will return an object as store's state (required)\n- `getters` - an object with methods which is similar to Vue's computed values or Vuex's getters, and details are below (optional)\n- `actions` - an object with methods which can do side effects and mutate state, and details are below (optional)\n\n### Getters\n\nWhen you define a store like this:\n\n```typescript\nconst store = defineStore({\n // ...other required fields\n getters: {\n getSomething() {\n return 'xxx'\n }\n }\n})\n```\n\nAnd you should use it like this:\n\n```typescript\nstore.getSomething\n```\n\ninstead of:\n\n```typescript\nstore.getSomething() // error\n```\n\nAdditionally, getters can access state and/or other getters via `this`, but state is read-only.\n\n### Actions\n\nWhen you define a store like this:\n\n```typescript\nconst store = defineStore({\n // ...other required fields\n actions: {\n doSideEffect() {\n this.xxx = 'xxx'\n return 'ok'\n }\n }\n})\n```\n\nUsing it is just to call it:\n\n```typescript\nconst returnValue = store.doSideEffect()\n```\n\nActions can return any value or return nothing, and it can receive any number of parameters with different types.\nParameters types and return type can't be lost, which means type-checking must be available at call side.\n\nState can be accessed and mutated via `this`. Getters can be accessed via `this` but they're read-only."},"template":"declare function defineStore(store: unknown): unknown\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nconst store = defineStore({\n id: '',\n state: () => ({\n num: 0,\n str: '',\n }),\n getters: {\n stringifiedNum() {\n // @ts-expect-error\n this.num += 1\n\n return this.num.toString()\n },\n parsedNum() {\n return parseInt(this.stringifiedNum)\n },\n },\n actions: {\n init() {\n this.reset()\n this.increment()\n },\n increment(step = 1) {\n this.num += step\n },\n reset() {\n this.num = 0\n\n // @ts-expect-error\n this.parsedNum = 0\n\n return true\n },\n setNum(value: number) {\n this.num = value\n },\n },\n})\n\n// @ts-expect-error\nstore.nopeStateProp\n// @ts-expect-error\nstore.nopeGetter\n// @ts-expect-error\nstore.stringifiedNum()\nstore.init()\n// @ts-expect-error\nstore.init(0)\nstore.increment()\nstore.increment(2)\n// @ts-expect-error\nstore.setNum()\n// @ts-expect-error\nstore.setNum('3')\nstore.setNum(3)\nconst r = store.reset()\n\ntype _tests = [\n Expect<Equal<typeof store.num, number>>,\n Expect<Equal<typeof store.str, string>>,\n Expect<Equal<typeof store.stringifiedNum, string>>,\n Expect<Equal<typeof store.parsedNum, number>>,\n Expect<Equal<typeof r, true>>,\n]\n"},{"no":1367,"difficulty":"medium","path":"01367-medium-remove-index-signature","info":{"en":{"difficulty":"medium","title":"Remove Index Signature","author":{"github":"hiroyaiizuka","name":"hiroya iizuka"}}},"readme":{"en":"Implement `RemoveIndexSignature<T>` , exclude the index signature from object types.\n\nFor example:\n\n```\n\ntype Foo = {\n [key: string]: any;\n foo(): void;\n}\n\ntype A = RemoveIndexSignature<Foo> // expected { foo(): void }\n\n```"},"template":"type RemoveIndexSignature<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype Foo = {\n [key: string]: any\n foo(): void\n}\n\ntype Bar = {\n [key: number]: any\n bar(): void\n}\n\ntype FooBar = {\n [key: symbol]: any\n foobar(): void\n}\n\ntype Baz = {\n bar(): void\n baz: string\n}\n\ntype cases = [\n Expect<Equal<RemoveIndexSignature<Foo>, { foo(): void }>>,\n Expect<Equal<RemoveIndexSignature<Bar>, { bar(): void }>>,\n Expect<Equal<RemoveIndexSignature<FooBar>, { foobar(): void }>>,\n Expect<Equal<RemoveIndexSignature<Baz>, { bar(): void; baz: string }>>,\n]\n"},{"no":1383,"difficulty":"hard","path":"01383-hard-camelize","info":{"en":{"difficulty":"hard","title":"Camelize","tags":["union","recursion"],"author":{"github":"denchiklut","name":"Denis"}}},"readme":{"en":"Implement Camelize which converts object from snake_case to to camelCase\n\n```ts\nCamelize<{\n some_prop: string, \n prop: { another_prop: string },\n array: [{ snake_case: string }]\n}>\n\n// expected to be\n// {\n// someProp: string, \n// prop: { anotherProp: string },\n// array: [{ snakeCase: string }]\n// }\n```"},"template":"type Camelize<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<\n Camelize<{\n some_prop: string\n prop: { another_prop: string }\n array: [{ snake_case: string }]\n }>,\n {\n someProp: string\n prop: { anotherProp: string }\n array: [{ snakeCase: string }]\n }\n >>,\n]\n"},{"no":1978,"difficulty":"medium","path":"01978-medium-percentage-parser","info":{"en":{"difficulty":"medium","title":"Percentage Parser","author":{"github":"SSShuai1999","name":"SSShuai1999"}}},"readme":{"zh-CN":"实现类型 PercentageParser<T extends string>。根据规则 `/^(\\+|\\-)?(\\d*)?(\\%)?$/` 匹配类型 T。\n\n匹配的结果由三部分组成,分别是:[`正负号`, `数字`, `单位`],如果没有匹配,则默认是空字符串。\n\n例如:\n\n```ts\ntype PString1 = ''\ntype PString2 = '+85%'\ntype PString3 = '-85%'\ntype PString4 = '85%'\ntype PString5 = '85'\n\ntype R1 = PercentageParser<PString1> // expected ['', '', '']\ntype R2 = PercentageParser<PString2> // expected [\"+\", \"85\", \"%\"]\ntype R3 = PercentageParser<PString3> // expected [\"-\", \"85\", \"%\"]\ntype R4 = PercentageParser<PString4> // expected [\"\", \"85\", \"%\"]\ntype R5 = PercentageParser<PString5> // expected [\"\", \"85\", \"\"]\n```","en":"Implement PercentageParser<T extends string>.\nAccording to the `/^(\\+|\\-)?(\\d*)?(\\%)?$/` regularity to match T and get three matches.\n\nThe structure should be: [`plus or minus`, `number`, `unit`]\nIf it is not captured, the default is an empty string.\n\nFor example:\n\n```ts\ntype PString1 = ''\ntype PString2 = '+85%'\ntype PString3 = '-85%'\ntype PString4 = '85%'\ntype PString5 = '85'\n\ntype R1 = PercentageParser<PString1> // expected ['', '', '']\ntype R2 = PercentageParser<PString2> // expected [\"+\", \"85\", \"%\"]\ntype R3 = PercentageParser<PString3> // expected [\"-\", \"85\", \"%\"]\ntype R4 = PercentageParser<PString4> // expected [\"\", \"85\", \"%\"]\ntype R5 = PercentageParser<PString5> // expected [\"\", \"85\", \"\"]\n```"},"template":"type PercentageParser<A extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype Case0 = ['', '', '']\ntype Case1 = ['+', '', '']\ntype Case2 = ['+', '1', '']\ntype Case3 = ['+', '100', '']\ntype Case4 = ['+', '100', '%']\ntype Case5 = ['', '100', '%']\ntype Case6 = ['-', '100', '%']\ntype Case7 = ['-', '100', '']\ntype Case8 = ['-', '1', '']\ntype Case9 = ['', '', '%']\ntype Case10 = ['', '1', '']\ntype Case11 = ['', '100', '']\n\ntype cases = [\n Expect<Equal<PercentageParser<''>, Case0>>,\n Expect<Equal<PercentageParser<'+'>, Case1>>,\n Expect<Equal<PercentageParser<'+1'>, Case2>>,\n Expect<Equal<PercentageParser<'+100'>, Case3>>,\n Expect<Equal<PercentageParser<'+100%'>, Case4>>,\n Expect<Equal<PercentageParser<'100%'>, Case5>>,\n Expect<Equal<PercentageParser<'-100%'>, Case6>>,\n Expect<Equal<PercentageParser<'-100'>, Case7>>,\n Expect<Equal<PercentageParser<'-1'>, Case8>>,\n Expect<Equal<PercentageParser<'%'>, Case9>>,\n Expect<Equal<PercentageParser<'1'>, Case10>>,\n Expect<Equal<PercentageParser<'100'>, Case11>>,\n]\n"},{"no":2059,"difficulty":"hard","path":"02059-hard-drop-string","info":{"en":{"difficulty":"hard","title":"Drop String","tags":["template-literal","infer"],"author":{"github":"CaptainOfPhB","name":"CaptainOfPhB"},"related":["2070"]}},"readme":{"en":"Drop the specified chars from a string.\n\nFor example:\n\n```ts\ntype Butterfly = DropString<'foobar!', 'fb'> // 'ooar!'\n```"},"template":"type DropString<S, R> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<DropString<'butter fly!', ''>, 'butter fly!'>>,\n Expect<Equal<DropString<'butter fly!', ' '>, 'butterfly!'>>,\n Expect<Equal<DropString<'butter fly!', 'but'>, 'er fly!'>>,\n Expect<Equal<DropString<' b u t t e r f l y ! ', 'but'>, ' e r f l y ! '>>,\n Expect<Equal<DropString<' butter fly! ', ' '>, 'butterfly!'>>,\n Expect<Equal<DropString<' b u t t e r f l y ! ', ' '>, 'butterfly!'>>,\n Expect<Equal<DropString<' b u t t e r f l y ! ', 'but'>, ' e r f l y ! '>>,\n Expect<Equal<DropString<' b u t t e r f l y ! ', 'tub'>, ' e r f l y ! '>>,\n Expect<Equal<DropString<' b u t t e r f l y ! ', 'b'>, ' u t t e r f l y ! '>>,\n Expect<Equal<DropString<' b u t t e r f l y ! ', 't'>, ' b u e r f l y ! '>>,\n]\n"},{"no":2070,"difficulty":"medium","path":"02070-medium-drop-char","info":{"en":{"difficulty":"medium","title":"Drop Char","tags":["template-literal","infer"],"author":{"github":"CaptainOfPhB","name":"CaptainOfPhB"},"related":["2059"]}},"readme":{"zh-CN":"从字符串中剔除指定字符。\n\n例如:\n\n```ts\ntype Butterfly = DropChar<' b u t t e r f l y ! ', ' '> // 'butterfly!'\n```","en":"Drop a specified char from a string.\n\nFor example:\n\n```ts\ntype Butterfly = DropChar<' b u t t e r f l y ! ', ' '> // 'butterfly!'\n```"},"template":"type DropChar<S, C> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n // @ts-expect-error\n Expect<Equal<DropChar<'butter fly!', ''>, 'butterfly!'>>,\n Expect<Equal<DropChar<'butter fly!', ' '>, 'butterfly!'>>,\n Expect<Equal<DropChar<'butter fly!', '!'>, 'butter fly'>>,\n Expect<Equal<DropChar<' butter fly! ', ' '>, 'butterfly!'>>,\n Expect<Equal<DropChar<' b u t t e r f l y ! ', ' '>, 'butterfly!'>>,\n Expect<Equal<DropChar<' b u t t e r f l y ! ', 'b'>, ' u t t e r f l y ! '>>,\n Expect<Equal<DropChar<' b u t t e r f l y ! ', 't'>, ' b u e r f l y ! '>>,\n]\n"},{"no":2257,"difficulty":"medium","path":"02257-medium-minusone","info":{"en":{"difficulty":"medium","title":"MinusOne","tags":["math"],"author":{"github":"fayzzzm","name":"Mustafo Faiz"}}},"readme":{"zh-CN":"给定一个正整数作为类型的参数,要求返回的类型是该数字减 1。\n\n例如:\n\n```ts\ntype Zero = MinusOne<1> // 0\ntype FiftyFour = MinusOne<55> // 54\n```","en":"Given a number (always positive) as a type. Your type should return the number decreased by one.\n\nFor example:\n\n```ts\ntype Zero = MinusOne<1> // 0\ntype FiftyFour = MinusOne<55> // 54\n```"},"template":"type MinusOne<T extends number> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<MinusOne<1>, 0>>,\n Expect<Equal<MinusOne<55>, 54>>,\n Expect<Equal<MinusOne<3>, 2>>,\n Expect<Equal<MinusOne<100>, 99>>,\n Expect<Equal<MinusOne<1101>, 1100>>,\n]\n"},{"no":2595,"difficulty":"medium","path":"02595-medium-pickbytype","info":{"en":{"difficulty":"medium","title":"PickByType","tags":["object"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["2852"]}},"readme":{"en":"From `T`, pick a set of properties whose type are assignable to `U`.\n\nFor Example\n\n```typescript\ntype OnlyBoolean = PickByType<{\n name: string\n count: number\n isReadonly: boolean\n isEnable: boolean\n}, boolean> // { isReadonly: boolean; isEnable: boolean; }\n```"},"template":"type PickByType<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ninterface Model {\n name: string\n count: number\n isReadonly: boolean\n isEnable: boolean\n}\n\ntype cases = [\n Expect<Equal<PickByType<Model, boolean>, { isReadonly: boolean; isEnable: boolean }>>,\n Expect<Equal<PickByType<Model, string>, { name: string }>>,\n Expect<Equal<PickByType<Model, number>, { count: number }>>,\n]\n"},{"no":2688,"difficulty":"medium","path":"02688-medium-startswith","info":{"en":{"difficulty":"medium","title":"StartsWith","tags":["template-literal"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["2693"]}},"readme":{"zh-CN":"实现`StartsWith<T, U>`,接收两个string类型参数,然后判断`T`是否以`U`开头,根据结果返回`true`或`false`\n\n例如:\n\n```typescript\ntype a = StartsWith<'abc', 'ac'> // expected to be false\ntype b = StartsWith<'abc', 'ab'> // expected to be true\ntype c = StartsWith<'abc', 'abcd'> // expected to be false\n```","en":"Implement `StartsWith<T, U>` which takes two exact string types and returns whether `T` starts with `U`\n\nFor example\n\n```typescript\ntype a = StartsWith<'abc', 'ac'> // expected to be false\ntype b = StartsWith<'abc', 'ab'> // expected to be true\ntype c = StartsWith<'abc', 'abcd'> // expected to be false\n```"},"template":"type StartsWith<T extends string, U extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<StartsWith<'abc', 'ac'>, false>>,\n Expect<Equal<StartsWith<'abc', 'ab'>, true>>,\n Expect<Equal<StartsWith<'abc', 'abcd'>, false>>,\n Expect<Equal<StartsWith<'abc', ''>, true>>,\n Expect<Equal<StartsWith<'abc', ' '>, false>>,\n]\n"},{"no":2693,"difficulty":"medium","path":"02693-medium-endswith","info":{"en":{"difficulty":"medium","title":"EndsWith","tags":["template-literal"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["2688"]}},"readme":{"zh-CN":"实现`EndsWith<T, U>`,接收两个string类型参数,然后判断`T`是否以`U`结尾,根据结果返回`true`或`false`\n\n例如:\n\n```typescript\ntype a = EndsWith<'abc', 'bc'> // expected to be false\ntype b = EndsWith<'abc', 'abc'> // expected to be true\ntype c = EndsWith<'abc', 'd'> // expected to be false\n```","en":"Implement `EndsWith<T, U>` which takes two exact string types and returns whether `T` ends with `U`\n\nFor example:\n\n```typescript\ntype a = EndsWith<'abc', 'bc'> // expected to be false\ntype b = EndsWith<'abc', 'abc'> // expected to be true\ntype c = EndsWith<'abc', 'd'> // expected to be false\n```"},"template":"type EndsWith<T extends string, U extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<EndsWith<'abc', 'bc'>, true>>,\n Expect<Equal<EndsWith<'abc', 'abc'>, true>>,\n Expect<Equal<EndsWith<'abc', 'd'>, false>>,\n]\n"},{"no":2757,"difficulty":"medium","path":"02757-medium-partialbykeys","info":{"en":{"difficulty":"medium","title":"PartialByKeys","tags":["object"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"zh-CN":"实现一个通用的`PartialByKeys<T, K>`,它接收两个类型参数`T`和`K`。\n\n`K`指定应设置为可选的`T`的属性集。当没有提供`K`时,它就和普通的`Partial<T>`一样使所有属性都是可选的。\n\n例如:\n\n```ts\ninterface User {\n name: string\n age: number\n address: string\n}\n\ntype UserPartialName = PartialByKeys<User, 'name'> // { name?:string; age:number; address:string }\n```","en":"Implement a generic `PartialByKeys<T, K>` which takes two type argument `T` and `K`.\n\n`K` specify the set of properties of `T` that should set to be optional. When `K` is not provided, it should make all properties optional just like the normal `Partial<T>`.\n\nFor example\n\n```typescript\ninterface User {\n name: string\n age: number\n address: string\n}\n\ntype UserPartialName = PartialByKeys<User, 'name'> // { name?:string; age:number; address:string }\n```"},"template":"type PartialByKeys<T, K> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ninterface User {\n name: string\n age: number\n address: string\n}\n\ninterface UserPartialName {\n name?: string\n age: number\n address: string\n}\n\ninterface UserPartialNameAndAge {\n name?: string\n age?: number\n address: string\n}\n\ntype cases = [\n Expect<Equal<PartialByKeys<User, 'name'>, UserPartialName>>,\n Expect<Equal<PartialByKeys<User, 'name' | 'unknown'>, UserPartialName>>,\n Expect<Equal<PartialByKeys<User, 'name' | 'age'>, UserPartialNameAndAge>>,\n Expect<Equal<PartialByKeys<User>, Partial<User>>>,\n]\n"},{"no":2759,"difficulty":"medium","path":"02759-medium-requiredbykeys","info":{"en":{"difficulty":"medium","title":"RequiredByKeys","tags":["object"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"zh-CN":"实现一个通用的`RequiredByKeys<T, K>`,它接收两个类型参数`T`和`K`。\n\n`K`指定应设为必选的`T`的属性集。当没有提供`K`时,它就和普通的`Required<T>`一样使所有的属性成为必选的。\n\n例如:\n\n```ts\ninterface User {\n name?: string\n age?: number\n address?: string\n}\n\ntype UserRequiredName = RequiredByKeys<User, 'name'> // { name: string; age?: number; address?: string }\n\n```","en":"Implement a generic `RequiredByKeys<T, K>` which takes two type argument `T` and `K`.\n\n`K` specify the set of properties of `T` that should set to be required. When `K` is not provided, it should make all properties required just like the normal `Required<T>`.\n\nFor example\n\n```typescript\ninterface User {\n name?: string\n age?: number\n address?: string\n}\n\ntype UserRequiredName = RequiredByKeys<User, 'name'> // { name: string; age?: number; address?: string }\n\n```"},"template":"type RequiredByKeys<T, K> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ninterface User {\n name?: string\n age?: number\n address?: string\n}\n\ninterface UserRequiredName {\n name: string\n age?: number\n address?: string\n}\n\ninterface UserRequiredNameAndAge {\n name: string\n age: number\n address?: string\n}\n\ntype cases = [\n Expect<Equal<RequiredByKeys<User, 'name'>, UserRequiredName>>,\n Expect<Equal<RequiredByKeys<User, 'name' | 'unknown'>, UserRequiredName>>,\n Expect<Equal<RequiredByKeys<User, 'name' | 'age'>, UserRequiredNameAndAge>>,\n Expect<Equal<RequiredByKeys<User>, Required<User>>>,\n]\n"},{"no":2793,"difficulty":"medium","path":"02793-medium-mutable","info":{"en":{"difficulty":"medium","title":"Mutable","tags":["readonly","object-keys"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Implement the generic ```Mutable<T>``` which makes all properties in ```T``` mutable (not readonly).\n\nFor example\n\n```typescript\ninterface Todo {\n readonly title: string\n readonly description: string\n readonly completed: boolean\n}\n\ntype MutableTodo = Mutable<Todo> // { title: string; description: string; completed: boolean; }\n\n```"},"template":"type Mutable<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ninterface Todo1 {\n title: string\n description: string\n completed: boolean\n meta: {\n author: string\n }\n}\n\ntype List = [1, 2, 3]\n\ntype cases = [\n Expect<Equal<Mutable<Readonly<Todo1>>, Todo1>>,\n Expect<Equal<Mutable<Readonly<List>>, List>>,\n]\n\ntype errors = [\n // @ts-expect-error\n Mutable<'string'>,\n // @ts-expect-error\n Mutable<0>,\n]\n"},{"no":2822,"difficulty":"hard","path":"02822-hard-split","info":{"en":{"difficulty":"hard","title":"Split","tags":["string","split","array","tuple"],"author":{"github":"jfet97","name":"Andrea Simone Costa"}}},"readme":{"en":"The well known `split()` method splits a string into an array of substrings by looking for a separator, and returns the new array. The goal of this challenge is to split a string, by using a separator, but in the type system!\n\nFor example:\n\n```ts\ntype result = Split<'Hi! How are you?', ' '> // should be ['Hi!', 'How', 'are', 'you?']\n```"},"template":"type Split<S extends string, SEP extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Split<'Hi! How are you?', 'z'>, ['Hi! How are you?']>>,\n Expect<Equal<Split<'Hi! How are you?', ' '>, ['Hi!', 'How', 'are', 'you?']>>,\n Expect<Equal<Split<'Hi! How are you?', ''>, ['H', 'i', '!', ' ', 'H', 'o', 'w', ' ', 'a', 'r', 'e', ' ', 'y', 'o', 'u', '?']>>,\n Expect<Equal<Split<'', ''>, []>>,\n Expect<Equal<Split<'', 'z'>, ['']>>,\n Expect<Equal<Split<string, 'whatever'>, string[]>>,\n]\n"},{"no":2828,"difficulty":"hard","path":"02828-hard-classpublickeys","info":{"en":{"difficulty":"hard","title":"ClassPublicKeys","tags":["utils"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Implement the generic `ClassPublicKeys<T>` which returns all public keys of a class.\n\nFor example:\n\n```ts\nclass A {\n public str: string\n protected num: number\n private bool: boolean\n getNum() {\n return Math.random()\n }\n}\n\ntype publicKyes = ClassPublicKeys<A> // 'str' | 'getNum'\n```"},"template":"type ClassPublicKeys = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nclass A {\n public str: string\n protected num: number\n private bool: boolean\n constructor() {\n this.str = 'naive'\n this.num = 19260917\n this.bool = true\n }\n\n getNum() {\n return Math.random()\n }\n}\n\ntype cases = [\n Expect<Equal<ClassPublicKeys<A>, 'str' | 'getNum'>>,\n]\n"},{"no":2852,"difficulty":"medium","path":"02852-medium-omitbytype","info":{"en":{"difficulty":"medium","title":"OmitByType","tags":["object"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["2595"]}},"readme":{"en":"From ```T```, pick a set of properties whose type are not assignable to ```U```.\n\nFor Example\n\n```typescript\ntype OmitBoolean = OmitByType<{\n name: string\n count: number\n isReadonly: boolean\n isEnable: boolean\n}, boolean> // { name: string; count: number }\n```"},"template":"type OmitByType<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ninterface Model {\n name: string\n count: number\n isReadonly: boolean\n isEnable: boolean\n}\n\ntype cases = [\n Expect<Equal<OmitByType<Model, boolean>, { name: string; count: number }>>,\n Expect<Equal<OmitByType<Model, string>, { count: number; isReadonly: boolean; isEnable: boolean }>>,\n Expect<Equal<OmitByType<Model, number>, { name: string; isReadonly: boolean; isEnable: boolean }>>,\n]\n"},{"no":2857,"difficulty":"hard","path":"02857-hard-isrequiredkey","info":{"en":{"difficulty":"hard","title":"IsRequiredKey","tags":["utils"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Implement a generic ```IsRequiredKey<T, K>``` that return whether ```K``` are required keys of ```T``` .\n\nFor example\n\n```typescript\ntype A = IsRequiredKey<{ a: number, b?: string },'a'> // true\ntype B = IsRequiredKey<{ a: number, b?: string },'b'> // false\ntype C = IsRequiredKey<{ a: number, b?: string },'b' | 'a'> // false\n```"},"template":"type IsRequiredKey<T, K extends keyof T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<IsRequiredKey<{ a: number; b?: string }, 'a'>, true>>,\n Expect<Equal<IsRequiredKey<{ a: number; b?: string }, 'b'>, false>>,\n Expect<Equal<IsRequiredKey<{ a: number; b?: string }, 'b' | 'a'>, false>>,\n]\n"},{"no":2946,"difficulty":"medium","path":"02946-medium-objectentries","info":{"en":{"difficulty":"medium","title":"ObjectEntries","tags":["object"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Implement the type version of ```Object.entries```\n\nFor example \n\n```typescript\ninterface Model {\n name: string;\n age: number;\n locations: string[] | null;\n}\ntype modelEntries = ObjectEntries<Model> // ['name', string] | ['age', number] | ['locations', string[] | null];\n```"},"template":"type ObjectEntries<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ninterface Model {\n name: string\n age: number\n locations: string[] | null\n}\n\ntype ModelEntries = ['name', string] | ['age', number] | ['locations', string[] | null]\n\ntype cases = [\n Expect<Equal<ObjectEntries<Model>, ModelEntries>>,\n Expect<Equal<ObjectEntries<Partial<Model>>, ModelEntries>>,\n Expect<Equal<ObjectEntries<{ key?: undefined }>, ['key', undefined]>>,\n Expect<Equal<ObjectEntries<{ key: undefined }>, ['key', undefined]>>,\n]\n"},{"no":2949,"difficulty":"hard","path":"02949-hard-objectfromentries","info":{"en":{"difficulty":"hard","title":"ObjectFromEntries","tags":["object"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["55"]}},"readme":{"en":"Implement the type version of ```Object.fromEntries```\n\nFor example:\n\n```typescript\ninterface Model {\n name: string;\n age: number;\n locations: string[] | null;\n}\n\ntype ModelEntries = ['name', string] | ['age', number] | ['locations', string[] | null];\n\ntype result = ObjectFromEntries<ModelEntries> // expected to be Model\n```"},"template":"type ObjectFromEntries<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ninterface Model {\n name: string\n age: number\n locations: string[] | null\n}\n\ntype ModelEntries = ['name', string] | ['age', number] | ['locations', string[] | null]\n\ntype cases = [\n Expect<Equal<ObjectFromEntries<ModelEntries>, Model>>,\n]\n"},{"no":3057,"difficulty":"easy","path":"03057-easy-push","info":{"en":{"difficulty":"easy","title":"Push","tags":["array"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["533","3060"]}},"readme":{"zh-CN":"在类型系统里实现通用的 ```Array.push``` 。\n\n举例如下,\n\n```typescript\ntype Result = Push<[1, 2], '3'> // [1, 2, '3']\n```","ko":"`Array.push`의 제네릭 버전을 구현하세요.\n\n예시:\n\n```typescript\ntype Result = Push<[1, 2], '3'> // [1, 2, '3']\n```","en":"Implement the generic version of ```Array.push```\n\nFor example\n\n```typescript\ntype Result = Push<[1, 2], '3'> // [1, 2, '3']\n```"},"template":"type Push<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Push<[], 1>, [1]>>,\n Expect<Equal<Push<[1, 2], '3'>, [1, 2, '3']>>,\n Expect<Equal<Push<['1', 2, '3'], boolean>, ['1', 2, '3', boolean]>>,\n]\n"},{"no":3060,"difficulty":"easy","path":"03060-easy-unshift","info":{"en":{"difficulty":"easy","title":"Unshift","tags":["array"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["533","3057"]}},"readme":{"zh-CN":"实现类型版本的 ```Array.unshift```。\n\n举例,\n\n```typescript\ntype Result = Unshift<[1, 2], 0> // [0, 1, 2,]\n```","ko":"`Array.unshift`의 타입 버전을 구현하세요.\n\n예시:\n\n```typescript\ntype Result = Unshift<[1, 2], 0> // [0, 1, 2,]\n```","en":"Implement the type version of ```Array.unshift```\n\nFor example\n\n```typescript\ntype Result = Unshift<[1, 2], 0> // [0, 1, 2,]\n```"},"template":"type Unshift<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Unshift<[], 1>, [1]>>,\n Expect<Equal<Unshift<[1, 2], 0>, [0, 1, 2 ]>>,\n Expect<Equal<Unshift<['1', 2, '3'], boolean>, [boolean, '1', 2, '3']>>,\n]\n"},{"no":3062,"difficulty":"medium","path":"03062-medium-shift","info":{"en":{"difficulty":"medium","title":"Shift","tags":["array"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["16"]}},"readme":{"en":"Implement the type version of ```Array.shift```\n\nFor example\n\n```typescript\ntype Result = Shift<[3, 2, 1]> // [2, 1]\n```"},"template":"type Shift<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Shift<[3, 2, 1]>, [2, 1]>>,\n Expect<Equal<Shift<['a', 'b', 'c', 'd' ]>, ['b', 'c', 'd']>>,\n]\n"},{"no":3188,"difficulty":"medium","path":"03188-medium-tuple-to-nested-object","info":{"en":{"difficulty":"medium","title":"Tuple to Nested Object","tags":["object"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["10","11","472","730"]}},"readme":{"en":"Given a tuple type ```T``` that only contains string type, and a type ```U```, build an object recursively.\n\n```typescript\ntype a = TupleToNestedObject<['a'], string> // {a: string}\ntype b = TupleToNestedObject<['a', 'b'], number> // {a: {b: number}}\ntype c = TupleToNestedObject<[], boolean> // boolean. if the tuple is empty, just return the U type\n```"},"template":"type TupleToNestedObject<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<TupleToNestedObject<['a'], string>, { a: string }>>,\n Expect<Equal<TupleToNestedObject<['a', 'b'], number>, { a: { b: number } }>>,\n Expect<Equal<TupleToNestedObject<['a', 'b', 'c'], boolean>, { a: { b: { c: boolean } } }>>,\n Expect<Equal<TupleToNestedObject<[], boolean>, boolean>>,\n]\n"},{"no":3192,"difficulty":"medium","path":"03192-medium-reverse","info":{"en":{"difficulty":"medium","title":"Reverse","tags":["tuple"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Implement the type version of ```Array.reverse```\n\nFor example:\n\n```typescript\ntype a = Reverse<['a', 'b']> // ['b', 'a']\ntype b = Reverse<['a', 'b', 'c']> // ['c', 'b', 'a']\n```"},"template":"type Reverse<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Reverse<[]>, []>>,\n Expect<Equal<Reverse<['a', 'b']>, ['b', 'a']>>,\n Expect<Equal<Reverse<['a', 'b', 'c']>, ['c', 'b', 'a']>>,\n]\n"},{"no":3196,"difficulty":"medium","path":"03196-medium-flip-arguments","info":{"en":{"difficulty":"medium","title":"Flip Arguments","tags":["arguments"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["3192"]}},"readme":{"en":"Implement the type version of lodash's ```_.flip```.\n\nType ```FlipArguments<T>``` requires function type ```T``` and returns a new function type which has the same return type of T but reversed parameters.\n\nFor example:\n\n```typescript\ntype Flipped = FlipArguments<(arg0: string, arg1: number, arg2: boolean) => void> \n// (arg0: boolean, arg1: number, arg2: string) => void\n```"},"template":"type FlipArguments<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<FlipArguments<() => boolean>, () => boolean>>,\n Expect<Equal<FlipArguments<(foo: string) => number>, (foo: string) => number>>,\n Expect<Equal<FlipArguments<(arg0: string, arg1: number, arg2: boolean) => void>, (arg0: boolean, arg1: number, arg2: string) => void>>,\n]\n"},{"no":3243,"difficulty":"medium","path":"03243-medium-flattendepth","info":{"en":{"difficulty":"medium","title":"FlattenDepth","tags":["array"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["459"]}},"readme":{"en":"Recursively flatten array up to depth times.\n\nFor example:\n\n```typescript\ntype a = FlattenDepth<[1, 2, [3, 4], [[[5]]]], 2> // [1, 2, 3, 4, [5]]. flattern 2 times\ntype b = FlattenDepth<[1, 2, [3, 4], [[[5]]]]> // [1, 2, 3, 4, [[5]]]. Depth defaults to be 1\n```\n\nIf the depth is provided, it's guaranteed to be positive integer."},"template":"type FlattenDepth = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<FlattenDepth<[]>, []>>,\n Expect<Equal<FlattenDepth<[1, 2, 3, 4]>, [1, 2, 3, 4]>>,\n Expect<Equal<FlattenDepth<[1, [2]]>, [1, 2]>>,\n Expect<Equal<FlattenDepth<[1, 2, [3, 4], [[[5]]]], 2>, [1, 2, 3, 4, [5]]>>,\n Expect<Equal<FlattenDepth<[1, 2, [3, 4], [[[5]]]]>, [1, 2, 3, 4, [[5]]]>>,\n Expect<Equal<FlattenDepth<[1, [2, [3, [4, [5]]]]], 3>, [1, 2, 3, 4, [5]]>>,\n Expect<Equal<FlattenDepth<[1, [2, [3, [4, [5]]]]], 19260817>, [1, 2, 3, 4, 5]>>,\n]\n"},{"no":3312,"difficulty":"easy","path":"03312-easy-parameters","info":{"en":{"difficulty":"easy","title":"Parameters","tags":["infer","tuple","built-in"],"author":{"github":"midorizemi","name":"midorizemi"}}},"readme":{"zh-CN":"实现内置的 Parameters<T> 类型,而不是直接使用它,可参考[TypeScript官方文档](https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype)。","ko":"내장 제네릭 `Parameters<T>`를 이를 사용하지 않고 구현하세요.","en":"Implement the built-in Parameters<T> generic without using it."},"template":"type MyParameters<T extends (...args: any[]) => any> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nconst foo = (arg1: string, arg2: number): void => {}\nconst bar = (arg1: boolean, arg2: { a: 'A' }): void => {}\nconst baz = (): void => {}\n\ntype cases = [\n Expect<Equal<MyParameters<typeof foo>, [string, number]>>,\n Expect<Equal<MyParameters<typeof bar>, [boolean, { a: 'A' }]>>,\n Expect<Equal<MyParameters<typeof baz>, []>>,\n]\n"},{"no":3326,"difficulty":"medium","path":"03326-medium-bem-style-string","info":{"en":{"difficulty":"medium","title":"BEM style string","tags":["template-literal","union","tuple"],"author":{"github":"songhn233","name":"Songhn"}}},"readme":{"en":"The Block, Element, Modifier methodology (BEM) is a popular naming convention for classes in CSS. \n\nFor example, the block component would be represented as `btn`, element that depends upon the block would be represented as `btn__price`, modifier that changes the style of the block would be represented as `btn--big` or `btn__price--warning`.\n\nImplement `BEM<B, E, M>` which generate string union from these three parameters. Where `B` is a string literal, `E` and `M` are string arrays (can be empty)."},"template":"type BEM<B extends string, E extends string[], M extends string[]> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<BEM<'btn', ['price'], []>, 'btn__price'>>,\n Expect<Equal<BEM<'btn', ['price'], ['warning', 'success']>, 'btn__price--warning' | 'btn__price--success' >>,\n Expect<Equal<BEM<'btn', [], ['small', 'medium', 'large']>, 'btn--small' | 'btn--medium' | 'btn--large' >>,\n]\n"},{"no":3376,"difficulty":"medium","path":"03376-medium-inordertraversal","info":{"en":{"difficulty":"hard","title":"InorderTraversal","tags":["object"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Implement the type version of binary tree inorder traversal.\n\nFor example:\n\n```typescript\nconst tree1 = {\n val: 1,\n left: null,\n right: {\n val: 2,\n left: {\n val: 3,\n left: null,\n right: null,\n },\n right: null,\n },\n} as const\n\ntype A = InorderTraversal<typeof tree1> // [1, 3, 2]\n```"},"template":"interface TreeNode {\n val: number\n left: TreeNode | null\n right: TreeNode | null\n}\ntype InorderTraversal<T extends TreeNode | null> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\nconst tree1 = {\n val: 1,\n left: null,\n right: {\n val: 2,\n left: {\n val: 3,\n left: null,\n right: null,\n },\n right: null,\n },\n} as const\n\nconst tree2 = {\n val: 1,\n left: null,\n right: null,\n} as const\n\nconst tree3 = {\n val: 1,\n left: {\n val: 2,\n left: null,\n right: null,\n },\n right: null,\n} as const\n\nconst tree4 = {\n val: 1,\n left: null,\n right: {\n val: 2,\n left: null,\n right: null,\n },\n} as const\n\ntype cases = [\n Expect<Equal<InorderTraversal<null>, []>>,\n Expect<Equal<InorderTraversal<typeof tree1>, [1, 3, 2]>>,\n Expect<Equal<InorderTraversal<typeof tree2>, [1]>>,\n Expect<Equal<InorderTraversal<typeof tree3>, [2, 1]>>,\n Expect<Equal<InorderTraversal<typeof tree4>, [1, 2]>>,\n]\n"},{"no":4037,"difficulty":"hard","path":"04037-hard-ispalindrome","info":{"en":{"difficulty":"hard","title":"IsPalindrome","tags":["string"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Implement type ```IsPalindrome<T>``` to check whether a string or number is palindrome.\n\nFor example:\n\n```typescript\nIsPalindrome<'abc'> // false\nIsPalindrome<121> // true\n```"},"template":"type IsPalindrome<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<IsPalindrome<'abc'>, false>>,\n Expect<Equal<IsPalindrome<'b'>, true>>,\n Expect<Equal<IsPalindrome<'abca'>, false>>,\n Expect<Equal<IsPalindrome<121>, true>>,\n Expect<Equal<IsPalindrome<19260817>, false>>,\n]\n"},{"no":4179,"difficulty":"medium","path":"04179-medium-flip","info":{"en":{"difficulty":"medium","title":"Flip","tags":["object"],"author":{"github":"kathawala","name":"Farhan Kathawala"}}},"readme":{"en":"Implement the type of `just-flip-object`. Examples:\n\n```typescript\nFlip<{ a: \"x\", b: \"y\", c: \"z\" }>; // {x: 'a', y: 'b', z: 'c'}\nFlip<{ a: 1, b: 2, c: 3 }>; // {1: 'a', 2: 'b', 3: 'c'}\nflip<{ a: false, b: true }>; // {false: 'a', true: 'b'}\n```\n\nNo need to support nested objects and values which cannot be object keys such as arrays"},"template":"type Flip<T> = any\n","tests":"import type { Equal, Expect, NotEqual } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<{ a: 'pi' }, Flip<{ pi: 'a' }>>>,\n Expect<NotEqual<{ b: 'pi' }, Flip<{ pi: 'a' }>>>,\n Expect<Equal<{ 3.14: 'pi'; true: 'bool' }, Flip<{ pi: 3.14; bool: true }>>>,\n Expect<Equal<{ val2: 'prop2'; val: 'prop' }, Flip<{ prop: 'val'; prop2: 'val2' }>>>,\n]\n"},{"no":4182,"difficulty":"medium","path":"04182-medium-fibonacci-sequence","info":{"zh-CN":{"title":"斐波那契序列"},"en":{"difficulty":"medium","title":"Fibonacci Sequence","author":{"github":"wind-liang","name":"windliang"}}},"readme":{"zh-CN":"Implement a generic Fibonacci\\<T\\> takes an number T and returns it's corresponding [Fibonacci number](https://en.wikipedia.org/wiki/Fibonacci_number).\n\nThe sequence starts:\n1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...\n\nFor example\n```js\ntype Result1 = Fibonacci<3> // 2\ntype Result2 = Fibonacci<8> // 21\n```","en":"Implement a generic Fibonacci\\<T\\> takes an number T and returns it's corresponding [Fibonacci number](https://en.wikipedia.org/wiki/Fibonacci_number).\n\nThe sequence starts:\n1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...\n\nFor example\n```ts\ntype Result1 = Fibonacci<3> // 2\ntype Result2 = Fibonacci<8> // 21\n```"},"template":"type Fibonacci<T extends number> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Fibonacci<3>, 2>>,\n Expect<Equal<Fibonacci<8>, 21>>,\n]\n"},{"no":4260,"difficulty":"medium","path":"04260-medium-nomiwase","info":{"ja":{"title":"文字の組み合わせ"},"en":{"difficulty":"medium","title":"AllCombinations","author":{"github":"sugoroku-y","name":"蛭子屋双六"}}},"readme":{"ja":"指定された文字列に含まれる文字をそれぞれ最大で1度だけ使った文字列のすべての組み合わせの型`AllCombinations`を実装します。\n\n例えば\n\n```ts\n\ntype AllCombinations_ABC = AllCombinations<'ABC'>;\n// should be '' | 'A' | 'B' | 'C' | 'AB' | 'AC' | 'BA' | 'BC' | 'CA' | 'CB' | 'ABC' | 'ACB' | 'BAC' | 'BCA' | 'CAB' | 'CBA'\n```","en":"Implement type ```AllCombinations<S>``` that return all combinations of strings which use characters from ```S``` at most once.\n\nFor example:\n\n```ts\ntype AllCombinations_ABC = AllCombinations<'ABC'>;\n// should be '' | 'A' | 'B' | 'C' | 'AB' | 'AC' | 'BA' | 'BC' | 'CA' | 'CB' | 'ABC' | 'ACB' | 'BAC' | 'BCA' | 'CAB' | 'CBA'\n```"},"template":"type AllCombinations<S> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<AllCombinations<''>, ''>>,\n Expect<Equal<AllCombinations<'A'>, '' | 'A'>>,\n Expect<Equal<AllCombinations<'AB'>, '' | 'A' | 'B' | 'AB' | 'BA'>>,\n Expect<Equal<AllCombinations<'ABC'>, '' | 'A' | 'B' | 'C' | 'AB' | 'AC' | 'BA' | 'BC' | 'CA' | 'CB' | 'ABC' | 'ACB' | 'BAC' | 'BCA' | 'CAB' | 'CBA'>>,\n Expect<Equal<AllCombinations<'ABCD'>, '' | 'A' | 'B' | 'C' | 'D' | 'AB' | 'AC' | 'AD' | 'BA' | 'BC' | 'BD' | 'CA' | 'CB' | 'CD' | 'DA' | 'DB' | 'DC' | 'ABC' | 'ABD' | 'ACB' | 'ACD' | 'ADB' | 'ADC' | 'BAC' | 'BAD' | 'BCA' | 'BCD' | 'BDA' | 'BDC' | 'CAB' | 'CAD' | 'CBA' | 'CBD' | 'CDA' | 'CDB' | 'DAB' | 'DAC' | 'DBA' | 'DBC' | 'DCA' | 'DCB' | 'ABCD' | 'ABDC' | 'ACBD' | 'ACDB' | 'ADBC' | 'ADCB' | 'BACD' | 'BADC' | 'BCAD' | 'BCDA' | 'BDAC' | 'BDCA' | 'CABD' | 'CADB' | 'CBAD' | 'CBDA' | 'CDAB' | 'CDBA' | 'DABC' | 'DACB' | 'DBAC' | 'DBCA' | 'DCAB' | 'DCBA'>>,\n]\n"},{"no":4425,"difficulty":"medium","path":"04425-medium-greater-than","info":{"en":{"difficulty":"medium","title":"Greater Than","tags":["array"],"author":{"github":"ch3cknull","name":"ch3cknull"}}},"readme":{"en":"In This Challenge, You should implement a type `GreaterThan<T, U>` like `T > U`\n\nNegative numbers do not need to be considered.\n\nFor example\n\n```ts\nGreaterThan<2, 1> //should be true\nGreaterThan<1, 1> //should be false\nGreaterThan<10, 100> //should be false\nGreaterThan<111, 11> //should be true\n```\n\nGood Luck!"},"template":"type GreaterThan<T extends number, U extends number> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<GreaterThan<1, 0>, true>>,\n Expect<Equal<GreaterThan<5, 4>, true>>,\n Expect<Equal<GreaterThan<4, 5>, false>>,\n Expect<Equal<GreaterThan<0, 0>, false>>,\n Expect<Equal<GreaterThan<20, 20>, false>>,\n Expect<Equal<GreaterThan<10, 100>, false>>,\n Expect<Equal<GreaterThan<111, 11>, true>>,\n]\n"},{"no":4471,"difficulty":"medium","path":"04471-medium-zip","info":{"en":{"difficulty":"medium","title":"Zip","tags":["tuple"],"author":{"github":"qianxi0410","name":"キリサメ qianxi"}}},"readme":{"en":"In This Challenge, You should implement a type `Zip<T, U>`, T and U must be `Tuple`\n```ts\ntype exp = Zip<[1, 2], [true, false]> // expected to be [[1, true], [2, false]]\n```"},"template":"type Zip = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Zip<[], []>, []>>,\n Expect<Equal<Zip<[1, 2], [true, false]>, [[1, true], [2, false]]>>,\n Expect<Equal<Zip<[1, 2, 3], ['1', '2']>, [[1, '1'], [2, '2']]>>,\n Expect<Equal<Zip<[], [1, 2, 3]>, []>>,\n Expect<Equal<Zip<[[1, 2]], [3]>, [[[1, 2], 3]]>>,\n]\n"},{"no":4484,"difficulty":"medium","path":"04484-medium-istuple","info":{"en":{"difficulty":"medium","title":"IsTuple","tags":["tuple"],"author":{"github":"jiangshanmeta","name":"jiangshan"},"related":["1042","1097","223"]}},"readme":{"en":"Implement a type ```IsTuple```, which takes an input type ```T``` and returns whether ```T``` is tuple type.\n\nFor example:\n\n```typescript\ntype case1 = IsTuple<[number]> // true\ntype case2 = IsTuple<readonly [number]> // true\ntype case3 = IsTuple<number[]> // false\n```"},"template":"type IsTuple<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<IsTuple<[]>, true>>,\n Expect<Equal<IsTuple<[number]>, true>>,\n Expect<Equal<IsTuple<readonly [1]>, true>>,\n Expect<Equal<IsTuple<{ length: 1 }>, false>>,\n Expect<Equal<IsTuple<number[]>, false>>,\n Expect<Equal<IsTuple<never>, false>>,\n]\n"},{"no":4499,"difficulty":"medium","path":"04499-medium-chunk","info":{"en":{"difficulty":"medium","title":"Chunk","tags":["tuple"],"author":{"github":"qianxi0410","name":"キリサメ qianxi"}}},"readme":{"en":"Do you know `lodash`? `Chunk` is a very useful function in it, now let's implement it.\n`Chunk<T, N>` accepts two required type parameters, the `T` must be a `tuple`, and the `N` must be an `integer >=1`\n\n```ts\ntype exp1 = Chunk<[1, 2, 3], 2> // expected to be [[1, 2], [3]]\ntype exp2 = Chunk<[1, 2, 3], 4> // expected to be [[1, 2, 3]]\ntype exp3 = Chunk<[1, 2, 3], 1> // expected to be [[1], [2], [3]]\n```"},"template":"type Chunk = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Chunk<[], 1>, []>>,\n Expect<Equal<Chunk<[1, 2, 3], 1>, [[1], [2], [3]]>>,\n Expect<Equal<Chunk<[1, 2, 3], 2>, [[1, 2], [3]]>>,\n Expect<Equal<Chunk<[1, 2, 3, 4], 2>, [[1, 2], [3, 4]]>>,\n Expect<Equal<Chunk<[1, 2, 3, 4], 5>, [[1, 2, 3, 4]]>>,\n Expect<Equal<Chunk<[1, true, 2, false], 2>, [[1, true], [2, false]]>>,\n]\n"},{"no":4518,"difficulty":"medium","path":"04518-medium-fill","info":{"en":{"difficulty":"medium","title":"Fill","tags":["tuple"],"author":{"github":"qianxi0410","name":"キリサメ qianxi"}}},"readme":{"en":"`Fill`, a common JavaScript function, now let us implement it with types.\n`Fill<T, N, Start?, End?>`, as you can see,`Fill` accepts four types of parameters, of which `T` and `N` are required parameters, and `Start` and `End` are optional parameters.\nThe requirements for these parameters are: `T` must be a `tuple`, `N` can be any type of value, `Start` and `End` must be integers greater than or equal to 0.\n\n```ts\ntype exp = Fill<[1, 2, 3], 0> // expected to be [0, 0, 0]\n```\nIn order to simulate the real function, the test may contain some boundary conditions, I hope you can enjoy it :)"},"template":"type Fill<\n T extends unknown[],\n N,\n Start extends number = 0,\n End extends number = T['length'],\n> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Fill<[], 0>, []>>,\n Expect<Equal<Fill<[], 0, 0, 3>, []>>,\n Expect<Equal<Fill<[1, 2, 3], 0, 0, 0>, [1, 2, 3]>>,\n Expect<Equal<Fill<[1, 2, 3], 0, 2, 2>, [1, 2, 3]>>,\n Expect<Equal<Fill<[1, 2, 3], 0>, [0, 0, 0]>>,\n Expect<Equal<Fill<[1, 2, 3], true>, [true, true, true]>>,\n Expect<Equal<Fill<[1, 2, 3], true, 0, 1>, [true, 2, 3]>>,\n Expect<Equal<Fill<[1, 2, 3], true, 1, 3>, [1, true, true]>>,\n Expect<Equal<Fill<[1, 2, 3], true, 10, 0>, [1, 2, 3]>>,\n Expect<Equal<Fill<[1, 2, 3], true, 0, 10>, [true, true, true]>>,\n]\n"},{"no":4803,"difficulty":"medium","path":"04803-medium-trim-right","info":{"en":{"difficulty":"medium","title":"Trim Right","author":{"github":"Talljack","name":"Yugang Cao"},"related":["106","108"]}},"readme":{"zh-CN":"实现 `TrimRight<T>` ,它接收确定的字符串类型并返回一个新的字符串,其中新返回的字符串删除了原字符串结尾的空白字符串。\n\n例如\n\n```ts\ntype Trimed = TrimLeft<' Hello World '> // 应推导出 ' Hello World'\n```","en":"Implement `TrimRight<T>` which takes an exact string type and returns a new string with the whitespace ending removed.\n\nFor example:\n\n```ts\ntype Trimed = TrimRight<' Hello World '> // expected to be ' Hello World'\n```"},"template":"type TrimRight<S extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<TrimRight<'str'>, 'str'>>,\n Expect<Equal<TrimRight<'str '>, 'str'>>,\n Expect<Equal<TrimRight<'str '>, 'str'>>,\n Expect<Equal<TrimRight<' str '>, ' str'>>,\n Expect<Equal<TrimRight<' foo bar \\n\\t '>, ' foo bar'>>,\n Expect<Equal<TrimRight<''>, ''>>,\n Expect<Equal<TrimRight<'\\n\\t '>, ''>>,\n]\n"},{"no":5117,"difficulty":"medium","path":"05117-medium-without","info":{"zh-CN":{"difficulty":"中等","title":"去除数组指定元素","tags":["联合类型","数组"],"author":{"github":"Pineapple0919","name":"Pineapple"}},"en":{"difficulty":"medium","title":"Without","tags":["union","array"],"author":{"github":"Pineapple0919","name":"Pineapple"}}},"readme":{"zh-CN":"实现一个像 Lodash.without 函数一样的泛型 Without<T, U>,它接收数组类型的 T 和数字或数组类型的 U 为参数,会返回一个去除 U 中元素的数组 T。\n\n例如:\n\n```ts\ntype Res = Without<[1, 2], 1>; // expected to be [2]\ntype Res1 = Without<[1, 2, 4, 1, 5], [1, 2]>; // expected to be [4, 5]\ntype Res2 = Without<[2, 3, 2, 3, 2, 3, 2, 3], [2, 3]>; // expected to be []\n```","en":"Implement the type version of Lodash.without, Without<T, U> takes an Array T, number or array U and returns an Array without the elements of U.\n\n```ts\ntype Res = Without<[1, 2], 1>; // expected to be [2]\ntype Res1 = Without<[1, 2, 4, 1, 5], [1, 2]>; // expected to be [4, 5]\ntype Res2 = Without<[2, 3, 2, 3, 2, 3, 2, 3], [2, 3]>; // expected to be []\n```"},"template":"type Without<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Without<[1, 2], 1>, [2]>>,\n Expect<Equal<Without<[1, 2, 4, 1, 5], [1, 2]>, [4, 5]>>,\n Expect<Equal<Without<[2, 3, 2, 3, 2, 3, 2, 3], [2, 3]>, []>>,\n]\n"},{"no":5140,"difficulty":"medium","path":"05140-medium-trunc","info":{"en":{"difficulty":"medium","title":"Trunc","tags":["template-literal"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Implement the type version of ```Math.trunc```, which takes string or number and returns the integer part of a number by removing any fractional digits.\n\nFor example:\n\n```typescript\ntype A = Trunc<12.34> // 12\n```"},"template":"type Trunc = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Trunc<0.1>, '0'>>,\n Expect<Equal<Trunc<1.234>, '1'>>,\n Expect<Equal<Trunc<12.345>, '12'>>,\n Expect<Equal<Trunc<-5.1>, '-5'>>,\n Expect<Equal<Trunc<'1.234'>, '1'>>,\n Expect<Equal<Trunc<'-10.234'>, '-10'>>,\n Expect<Equal<Trunc<10>, '10'>>,\n]\n"},{"no":5153,"difficulty":"medium","path":"05153-medium-indexof","info":{"en":{"difficulty":"medium","title":"IndexOf","tags":["array"],"author":{"github":"Pineapple0919","name":"Pineapple"}}},"readme":{"en":"Implement the type version of Array.indexOf, indexOf<T, U> takes an Array T, any U and returns the index of the first U in Array T.\n\n```ts\ntype Res = IndexOf<[1, 2, 3], 2>; // expected to be 1\ntype Res1 = IndexOf<[2,6, 3,8,4,1,7, 3,9], 3>; // expected to be 2\ntype Res2 = IndexOf<[0, 0, 0], 2>; // expected to be -1\n```"},"template":"type IndexOf<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<IndexOf<[1, 2, 3], 2>, 1>>,\n Expect<Equal<IndexOf<[2, 6, 3, 8, 4, 1, 7, 3, 9], 3>, 2>>,\n Expect<Equal<IndexOf<[0, 0, 0], 2>, -1>>,\n Expect<Equal<IndexOf<[string, 1, number, 'a'], number>, 2>>,\n Expect<Equal<IndexOf<[string, 1, number, 'a', any], any>, 4>>,\n]\n"},{"no":5181,"difficulty":"hard","path":"05181-hard-mutable-keys","info":{"en":{"difficulty":"hard","title":"Mutable Keys","tags":["utils"],"related":["2793"],"author":{"github":"Talljack","name":"Yugang Cao"}}},"readme":{"en":"Implement the advanced util type MutableKeys<T>, which picks all the mutable (not readonly) keys into a union.\n\nFor example:\n\n```ts\ntype Keys = MutableKeys<{ readonly foo: string; bar: number }>;\n// expected to be “bar”\n```"},"template":"type MutableKeys<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<MutableKeys<{ a: number; readonly b: string }>, 'a'>>,\n Expect<Equal<MutableKeys<{ a: undefined; readonly b: undefined }>, 'a'>>,\n Expect<Equal<MutableKeys<{ a: undefined; readonly b?: undefined; c: string; d: null }>, 'a' | 'c' | 'd'>>,\n Expect<Equal<MutableKeys<{}>, never>>,\n]\n"},{"no":5310,"difficulty":"medium","path":"05310-medium-join","info":{"en":{"difficulty":"medium","title":"Join","tags":["array"],"author":{"github":"Pineapple0919","name":"Pineapple"}}},"readme":{"en":"Implement the type version of Array.join, Join<T, U> takes an Array T, string or number U and returns the Array T with U stitching up.\n\n```ts\ntype Res = Join<[\"a\", \"p\", \"p\", \"l\", \"e\"], \"-\">; // expected to be 'a-p-p-l-e'\ntype Res1 = Join<[\"Hello\", \"World\"], \" \">; // expected to be 'Hello World'\ntype Res2 = Join<[\"2\", \"2\", \"2\"], 1>; // expected to be '21212'\ntype Res3 = Join<[\"o\"], \"u\">; // expected to be 'o'\n```"},"template":"type Join<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Join<['a', 'p', 'p', 'l', 'e'], '-'>, 'a-p-p-l-e'>>,\n Expect<Equal<Join<['Hello', 'World'], ' '>, 'Hello World'>>,\n Expect<Equal<Join<['2', '2', '2'], 1>, '21212'>>,\n Expect<Equal<Join<['o'], 'u'>, 'o'>>,\n]\n"},{"no":5317,"difficulty":"medium","path":"05317-medium-lastindexof","info":{"en":{"difficulty":"medium","title":"LastIndexOf","tags":["array"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Implement the type version of ```Array.lastIndexOf```, ```LastIndexOf<T, U>``` takes an Array ```T```, any ```U``` and returns the index of the last ```U``` in Array ```T```\n\nFor example:\n\n```typescript\ntype Res1 = LastIndexOf<[1, 2, 3, 2, 1], 2> // 3\ntype Res2 = LastIndexOf<[0, 0, 0], 2> // -1\n```"},"template":"type LastIndexOf<T, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<LastIndexOf<[1, 2, 3, 2, 1], 2>, 3>>,\n Expect<Equal<LastIndexOf<[2, 6, 3, 8, 4, 1, 7, 3, 9], 3>, 7>>,\n Expect<Equal<LastIndexOf<[0, 0, 0], 2>, -1>>,\n Expect<Equal<LastIndexOf<[string, 2, number, 'a', number, 1], number>, 4>>,\n Expect<Equal<LastIndexOf<[string, any, 1, number, 'a', any, 1], any>, 5>>,\n]\n"},{"no":5360,"difficulty":"medium","path":"05360-medium-unique","info":{"en":{"difficulty":"medium","title":"Unique","tags":["array"],"author":{"github":"Pineapple0919","name":"Pineapple"}}},"readme":{"en":"Implement the type version of Lodash.uniq, Unique<T> takes an Array T, returns the Array T without repeated values.\n\n```ts\ntype Res = Unique<[1, 1, 2, 2, 3, 3]>; // expected to be [1, 2, 3]\ntype Res1 = Unique<[1, 2, 3, 4, 4, 5, 6, 7]>; // expected to be [1, 2, 3, 4, 5, 6, 7]\ntype Res2 = Unique<[1, \"a\", 2, \"b\", 2, \"a\"]>; // expected to be [1, \"a\", 2, \"b\"]\ntype Res3 = Unique<[string, number, 1, \"a\", 1, string, 2, \"b\", 2, number]>; // expected to be [string, number, 1, \"a\", 2, \"b\"]\ntype Res4 = Unique<[unknown, unknown, any, any, never, never]>; // expected to be [unknown, any, never]\n```"},"template":"type Unique<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Unique<[1, 1, 2, 2, 3, 3]>, [1, 2, 3]>>,\n Expect<Equal<Unique<[1, 2, 3, 4, 4, 5, 6, 7]>, [1, 2, 3, 4, 5, 6, 7]>>,\n Expect<Equal<Unique<[1, 'a', 2, 'b', 2, 'a']>, [1, 'a', 2, 'b']>>,\n Expect<Equal<Unique<[string, number, 1, 'a', 1, string, 2, 'b', 2, number]>, [string, number, 1, 'a', 2, 'b']>>,\n Expect<Equal<Unique<[unknown, unknown, any, any, never, never]>, [unknown, any, never]>>,\n]\n"},{"no":5423,"difficulty":"hard","path":"05423-hard-intersection","info":{"en":{"difficulty":"hard","title":"Intersection","tags":["union","array"],"author":{"github":"Pineapple0919","name":"Pineapple"}}},"readme":{"en":"Implement the type version of Lodash.intersection, but there is a little different, Intersection<T> takes an Array T containing several arrays or any type element that includes the union type, returns a new array containing all incoming array intersection elements.\n\n```ts\ntype Res = Intersection<[[1, 2], [2, 3], [2, 2]]>; // expected to be 2\ntype Res1 = Intersection<[[1, 2, 3], [2, 3, 4], [2, 2, 3]]>; // expected to be 2 | 3\ntype Res2 = Intersection<[[1, 2], [3, 4], [5, 6]]>; // expected to be never\ntype Res3 = Intersection<[[1, 2, 3], [2, 3, 4], 3]>; // expected to be 3\ntype Res4 = Intersection<[[1, 2, 3], 2 | 3 | 4, 2 | 3]>; // expected to be 2 | 3\ntype Res5 = Intersection<[[1, 2, 3], 2, 3]>; // expected to be never\n```"},"template":"type Intersection<T> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Intersection<[[1, 2], [2, 3], [2, 2]]>, 2>>,\n Expect<Equal<Intersection<[[1, 2, 3], [2, 3, 4], [2, 2, 3]]>, 2 | 3>>,\n Expect<Equal<Intersection<[[1, 2], [3, 4], [5, 6]]>, never>>,\n Expect<Equal<Intersection<[[1, 2, 3], [2, 3, 4], 3]>, 3>>,\n Expect<Equal<Intersection<[[1, 2, 3], 2 | 3 | 4, 2 | 3]>, 2 | 3>>,\n Expect<Equal<Intersection<[[1, 2, 3], 2, 3]>, never>>,\n]\n"},{"no":5821,"difficulty":"medium","path":"05821-medium-maptypes","info":{"en":{"difficulty":"medium","title":"MapTypes","tags":["map","object","utils"],"author":{"github":"wokayme","name":"Krzysztof \"Wokay\" Łokaj"}}},"readme":{"en":"Implement `MapTypes<T, R>` which will transform types in object T to different types defined by type R which has the following structure\n\n```ts\ntype StringToNumber = {\n mapFrom: string; // value of key which value is string\n mapTo: number; // will be transformed for number\n}\n```\n\n## Examples:\n\n```ts\ntype StringToNumber = { mapFrom: string; mapTo: number;}\nMapTypes<{iWillBeANumberOneDay: string}, StringToNumber> // gives { iWillBeANumberOneDay: number; }\n```\n\nBe aware that user can provide a union of types:\n```ts\ntype StringToNumber = { mapFrom: string; mapTo: number;}\ntype StringToDate = { mapFrom: string; mapTo: Date;}\nMapTypes<{iWillBeNumberOrDate: string}, StringToDate | StringToNumber> // gives { iWillBeNumberOrDate: number | Date; }\n```\n\nIf the type doesn't exist in our map, leave it as it was:\n```ts\ntype StringToNumber = { mapFrom: string; mapTo: number;}\nMapTypes<{iWillBeANumberOneDay: string, iWillStayTheSame: Function}, StringToNumber> // // gives { iWillBeANumberOneDay: number, iWillStayTheSame: Function }\n```"},"template":"type MapTypes<T, R> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<MapTypes<{ stringToArray: string }, { mapFrom: string; mapTo: [] }>, { stringToArray: [] }>>,\n Expect<Equal<MapTypes<{ stringToNumber: string }, { mapFrom: string; mapTo: number }>, { stringToNumber: number }>>,\n Expect<Equal<MapTypes<{ stringToNumber: string; skipParsingMe: boolean }, { mapFrom: string; mapTo: number }>, { stringToNumber: number; skipParsingMe: boolean }>>,\n Expect<Equal<MapTypes<{ date: string }, { mapFrom: string; mapTo: Date } | { mapFrom: string; mapTo: null }>, { date: null | Date }>>,\n Expect<Equal<MapTypes<{ date: string }, { mapFrom: string; mapTo: Date | null }>, { date: null | Date }>>,\n Expect<Equal<MapTypes<{ fields: Record<string, boolean> }, { mapFrom: Record<string, boolean>; mapTo: string[] }>, { fields: string[] }>>,\n Expect<Equal<MapTypes<{ name: string }, { mapFrom: boolean; mapTo: never }>, { name: string }>>,\n Expect<Equal<MapTypes<{ name: string; date: Date }, { mapFrom: string; mapTo: boolean } | { mapFrom: Date; mapTo: string }>, { name: boolean; date: string }>>,\n]\n"},{"no":6141,"difficulty":"hard","path":"06141-hard-binary-to-decimal","info":{"en":{"difficulty":"hard","title":"Binary to Decimal","tags":["math"],"author":{"github":"wotsushi","name":"wotsushi"}}},"readme":{"en":"Implement `BinaryToDecimal<S>` which takes an exact string type `S` consisting 0 and 1 and returns an exact number type corresponding with `S` when `S` is regarded as a binary.\nYou can assume that the length of `S` is equal to or less than 8 and `S` is not empty.\n\n```ts\ntype Res1 = BinaryToDecimal<'10'>; // expected to be 2\ntype Res2 = BinaryToDecimal<'0011'>; // expected to be 3\n```"},"template":"type BinaryToDecimal<S extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<BinaryToDecimal<'10'>, 2>>,\n Expect<Equal<BinaryToDecimal<'0011'>, 3>>,\n Expect<Equal<BinaryToDecimal<'00000000'>, 0>>,\n Expect<Equal<BinaryToDecimal<'11111111'>, 255>>,\n Expect<Equal<BinaryToDecimal<'10101010'>, 170>>,\n]\n"},{"no":6228,"difficulty":"extreme","path":"06228-extreme-json-parser","info":{"en":{"difficulty":"extreme","title":"JSON Parser","tags":["template-literal","json"],"author":{"github":"hyroge","name":"Hydrogen"}}},"readme":{"en":"You're required to implement a type-level partly parser to parse JSON string into a object literal type.\n\nRequirements:\n - `Numbers` and `Unicode escape (\\uxxxx)` in JSON can be ignored. You needn't to parse them."},"template":"type Pure<T> = {\n [P in keyof T]: T[P] extends object ? Pure<T[P]> : T[P]\n}\n\ntype SetProperty<T, K extends PropertyKey, V> = {\n [P in (keyof T) | K]: P extends K ? V : P extends keyof T ? T[P] : never\n}\n\ntype Token = any\ntype ParseResult<T, K extends Token[]> = [T, K]\ntype Tokenize<T extends string, S extends Token[] = []> = Token[]\ntype ParseLiteral<T extends Token[]> = ParseResult<any, T>\n\ntype Parse<T extends string> = Pure<ParseLiteral<Tokenize<T>>[0]>\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<(\n Parse<`\n {\n \"a\": \"b\", \n \"b\": false, \n \"c\": [true, false, \"hello\", {\n \"a\": \"b\", \n \"b\": false\n }], \n \"nil\": null\n }\n `>\n ), (\n {\n nil: null\n c: [true, false, 'hello', {\n a: 'b'\n b: false\n }]\n b: false\n a: 'b'\n }\n\n )>>,\n Expect<Equal<Parse<'{}'>, {}>>,\n\n Expect<Equal<Parse<'[]'>, []>>,\n\n Expect<Equal<Parse<'[1]'>, never>>,\n\n Expect<Equal<Parse<'true'>, true>>,\n\n Expect<Equal<\n Parse<'[\"Hello\", true, false, null]'>,\n ['Hello', true, false, null]\n >>,\n\n Expect<Equal<\n (\n Parse<`\n {\n \"hello\\\\r\\\\n\\\\b\\\\f\": \"world\"\n }`>\n ), (\n {\n 'hello\\r\\n\\b\\f': 'world'\n }\n )\n >>,\n\n Expect<Equal<Parse<'{ 1: \"world\" }'>, never>>,\n\n Expect<Equal<Parse<`{ \"hello\n \n world\": 123 }`>, never>>,\n]\n"},{"no":7258,"difficulty":"hard","path":"07258-hard-object-key-paths","info":{"en":{"difficulty":"hard","title":"Object Key Paths","tags":["object-keys"],"author":{"github":"ChenKS12138","name":"CattChen"}}},"readme":{"en":"Get all possible paths that could be called by [_.get](https://lodash.com/docs/4.17.15#get) (a lodash function) to get the value of an object\n\n```typescript\ntype T1 = ObjectKeyPaths<{ name: string; age: number }>; // expected to be 'name' | 'age'\ntype T2 = ObjectKeyPaths<{\n refCount: number;\n person: { name: string; age: number };\n}>; // expected to be 'refCount' | 'person' | 'person.name' | 'person.age'\ntype T3 = ObjectKeyPaths<{ books: [{ name: string; price: number }] }>; // expected to be the superset of 'books' | 'books.0' | 'books[0]' | 'books.[0]' | 'books.0.name' | 'books.0.price' | 'books.length' | 'books.find'\n```"},"template":"type ObjectKeyPaths<T extends object> = any\n","tests":"import type { Equal, Expect, ExpectExtends } from '@type-challenges/utils'\n\nconst ref = {\n count: 1,\n person: {\n name: 'cattchen',\n age: 22,\n books: ['book1', 'book2'],\n pets: [\n {\n type: 'cat',\n },\n ],\n },\n}\n\ntype cases = [\n Expect<Equal<ObjectKeyPaths<{ name: string; age: number }>, 'name' | 'age'>>,\n Expect<\n Equal<\n ObjectKeyPaths<{\n refCount: number\n person: { name: string; age: number }\n }>,\n 'refCount' | 'person' | 'person.name' | 'person.age'\n >\n >,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'count'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person.name'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person.age'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person.books'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person.pets'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person.books.0'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person.books.1'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person.books[0]'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person.books.[0]'>>,\n Expect<ExpectExtends<ObjectKeyPaths<typeof ref>, 'person.pets.0.type'>>,\n Expect<Equal<ExpectExtends<ObjectKeyPaths<typeof ref>, 'notExist'>, false>>,\n]\n"},{"no":7544,"difficulty":"medium","path":"07544-medium-construct-tuple","info":{"en":{"difficulty":"medium","title":"Construct Tuple","tags":["tuple"],"author":{"github":"LoTwT","name":"Lo"}}},"readme":{"en":"Construct a tuple with a given length.\n\nFor example\n\n```ts\ntype result = ConstructTuple<2> // expect to be [unknown, unkonwn]\n```"},"template":"type ConstructTuple<L extends number> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<ConstructTuple<0>, []>>,\n Expect<Equal<ConstructTuple<2>, [unknown, unknown]>>,\n Expect<Equal<ConstructTuple<999>['length'], 999>>,\n // @ts-expect-error\n Expect<Equal<ConstructTuple<1000>['length'], 1000>>,\n]\n"},{"no":7561,"difficulty":"extreme","path":"07561-extreme-subtract","info":{"en":{"difficulty":"extreme","title":"Subtract","tags":["tuple"],"author":{"github":"LoTwT","name":"Lo"}}},"readme":{"en":"Implement the type Subtraction that is ` - ` in Javascript by using BuildTuple.\n\nIf the minuend is less than the subtrahend, it should be `never`.\n\nIt's a simple version.\n\nFor example\n\n```ts\nSubtract<2, 1> // expect to be 1\nSubtract<1, 2> // expect to be never\n```"},"template":"// M => minuend, S => subtrahend\ntype Subtract<M extends number, S extends number> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Subtract<1, 1>, 0>>,\n Expect<Equal<Subtract<2, 1>, 1>>,\n Expect<Equal<Subtract<1, 2>, never>>,\n // @ts-expect-error\n Expect<Equal<Subtract<1000, 999>, 1>>,\n]\n"},{"no":8640,"difficulty":"medium","path":"08640-medium-number-range","info":{"en":{"difficulty":"medium","title":"Number Range","author":{"github":"HongxuanG","name":"AaronGuo"}}},"readme":{"en":"Sometimes we want to limit the range of numbers...\nFor examples.\n```\ntype result = NumberRange<2 , 9> // | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 \n```"},"template":"type NumberRange<L, H> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\ntype Result1 = | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9\ntype Result2 = | 0 | 1 | 2\ntype Result3 =\n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10\n | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20\n | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30\n | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40\n | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50\n | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60\n | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70\n | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80\n | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90\n | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100\n | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110\n | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120\n | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130\n | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140\ntype cases = [\n Expect<Equal<NumberRange<2, 9>, Result1>>,\n Expect<Equal<NumberRange<0, 2>, Result2>>,\n Expect<Equal<NumberRange<0, 140>, Result3>>,\n]\n"},{"no":8767,"difficulty":"medium","path":"08767-medium-combination","info":{"en":{"difficulty":"medium","title":"Combination","tags":["array","application","string"],"author":{"github":"HomyeeKing","name":"Homyee King"},"related":["296"]}},"readme":{"en":"Given an array of strings, do Permutation & Combination.\nIt's also useful for the prop types like video [controlsList](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/controlsList)\n\n```ts\n// expected to be `\"foo\" | \"bar\" | \"baz\" | \"foo bar\" | \"foo bar baz\" | \"foo baz\" | \"foo baz bar\" | \"bar foo\" | \"bar foo baz\" | \"bar baz\" | \"bar baz foo\" | \"baz foo\" | \"baz foo bar\" | \"baz bar\" | \"baz bar foo\"`\ntype Keys = Combination<['foo', 'bar', 'baz']>\n```"},"template":"type Combination<T extends string[]> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\n\ntype cases = [\n Expect<Equal<Combination<['foo', 'bar', 'baz']>,\n 'foo' | 'bar' | 'baz' | 'foo bar' | 'foo bar baz' | 'foo baz' | 'foo baz bar' | 'bar foo' | 'bar foo baz' | 'bar baz' | 'bar baz foo' | 'baz foo' | 'baz foo bar' | 'baz bar' | 'baz bar foo'>>,\n]\n"},{"no":8804,"difficulty":"hard","path":"08804-hard-two-sum","info":{"en":{"difficulty":"hard","title":"Two Sum","tags":["array","math"],"author":{"github":"Psilocine","name":"PsiloLau"}}},"readme":{"en":"Given an array of integers `nums` and an integer `target`, return true if two numbers such that they add up to `target`."},"template":"type TwoSum<T extends number[], U extends number> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\r\n\r\ntype cases = [\r\n Expect<Equal<TwoSum<[3, 3], 6>, true>>,\r\n Expect<Equal<TwoSum<[3, 2, 4], 6>, true>>,\r\n Expect<Equal<TwoSum<[2, 7, 11, 15], 15>, false>>,\r\n Expect<Equal<TwoSum<[2, 7, 11, 15], 9>, true>>,\r\n Expect<Equal<TwoSum<[1, 2, 3], 0>, false>>,\r\n Expect<Equal<TwoSum<[1, 2, 3], 1>, false>>,\r\n Expect<Equal<TwoSum<[1, 2, 3], 2>, false>>,\r\n Expect<Equal<TwoSum<[1, 2, 3], 3>, true>>,\r\n Expect<Equal<TwoSum<[1, 2, 3], 4>, true>>,\r\n Expect<Equal<TwoSum<[1, 2, 3], 5>, true>>,\r\n Expect<Equal<TwoSum<[1, 2, 3], 6>, false>>,\r\n]\r\n"},{"no":8987,"difficulty":"medium","path":"08987-medium-subsequence","info":{"en":{"difficulty":"medium","title":"Subsequence","tags":["union"],"author":{"github":"jiangshanmeta","name":"jiangshan"}}},"readme":{"en":"Given an array of unique elements, return all possible subsequences.\r\n\r\nA subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements.\r\n\r\nFor example: \r\n\r\n```typescript\r\ntype A = Subsequence<[1, 2] // [] | [1] | [2] | [1, 2]\r\n```"},"template":"type Subsequence<T extends any[]> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\r\n\r\ntype cases = [\r\n Expect<Equal<Subsequence<[1, 2]>, [] | [1] | [2] | [1, 2]>>,\r\n Expect<Equal<Subsequence<[1, 2, 3]>, [] | [1] | [2] | [1, 2] | [3] | [1, 3] | [2, 3] | [1, 2, 3] >>,\r\n]\n"},{"no":9155,"difficulty":"hard","path":"09155-hard-validdate","info":{"en":{"difficulty":"hard","title":"ValidDate","author":{"github":"ch3cknull","name":"ch3cknull"}}},"readme":{"en":"Implement a type `ValidDate`, which takes an input type T and returns whether T is a valid date.\r\n\r\n**Leap year is not considered**\r\n\r\nGood Luck!\r\n\r\n```ts\r\nValidDate<'0102'> // true\r\nValidDate<'0131'> // true\r\nValidDate<'1231'> // true\r\nValidDate<'0229'> // false\r\nValidDate<'0100'> // false\r\nValidDate<'0132'> // false\r\nValidDate<'1301'> // false\r\n```"},"template":"type ValidDate<T extends string> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\r\n\r\ntype cases = [\r\n Expect<Equal<ValidDate<'0102'>, true>>,\r\n Expect<Equal<ValidDate<'0131'>, true>>,\r\n Expect<Equal<ValidDate<'1231'>, true>>,\r\n Expect<Equal<ValidDate<'0229'>, false>>,\r\n Expect<Equal<ValidDate<'0100'>, false>>,\r\n Expect<Equal<ValidDate<'0132'>, false>>,\r\n Expect<Equal<ValidDate<'1301'>, false>>,\r\n]\n"},{"no":9160,"difficulty":"hard","path":"09160-hard-assign","info":{"en":{"difficulty":"hard","title":"Assign","tags":["object","array"],"author":{"github":"workkk98","name":"zhangxiaofan"}}},"readme":{"en":"You have a target object and a source array of objects. You need to copy property from source to target, if it has the same property as the source, you should always keep the source property, and drop the target property. (Inspired by the `Object.assign` API)\r\n\r\n### example\r\n\r\n```ts\r\ntype Target = {\r\n a: 'a'\r\n}\r\n\r\ntype Origin1 = {\r\n b: 'b'\r\n}\r\n\r\n// type Result = Assign<Target, [Origin1]>\r\ntype Result = {\r\n a: 'a'\r\n b: 'b'\r\n}\r\n```\r\n\r\n\r\n```ts\r\ntype Target = {\r\n a: 'a'\r\n d: { \r\n hi: 'hi'\r\n }\r\n}\r\n\r\ntype Origin1 = {\r\n a: 'a1',\r\n b: 'b'\r\n}\r\n\r\n\r\ntype Origin2 = {\r\n b: 'b2',\r\n c: 'c'\r\n}\r\n\r\ntype Answer = {\r\n a: 'a1',\r\n b: 'b2',\r\n c: 'c'\r\n d: { \r\n hi: 'hi'\r\n }\r\n}\r\n```"},"template":"type Assign<T extends Record<string, unknown>, U> = any\n","tests":"import type { Equal, Expect } from '@type-challenges/utils'\r\n\r\n// case1\r\ntype Case1Target = {}\r\n\r\ntype Case1Origin1 = {\r\n a: 'a'\r\n}\r\n\r\ntype Case1Origin2 = {\r\n b: 'b'\r\n}\r\n\r\ntype Case1Origin3 = {\r\n c: 'c'\r\n}\r\n\r\ntype Case1Answer = {\r\n a: 'a'\r\n b: 'b'\r\n c: 'c'\r\n}\r\n\r\n// case2\r\ntype Case2Target = {\r\n a: [1, 2, 3]\r\n}\r\n\r\ntype Case2Origin1 = {\r\n a: {\r\n a1: 'a1'\r\n }\r\n}\r\n\r\ntype Case2Origin2 = {\r\n b: [2, 3, 3]\r\n}\r\n\r\ntype Case2Answer = {\r\n a: {\r\n a1: 'a1'\r\n }\r\n b: [2, 3, 3]\r\n}\r\n\r\n// case3\r\n\r\ntype Case3Target = {\r\n a: 1\r\n b: ['b']\r\n}\r\n\r\ntype Case3Origin1 = {\r\n a: 2\r\n b: {\r\n b: 'b'\r\n }\r\n c: 'c1'\r\n}\r\n\r\ntype Case3Origin2 = {\r\n a: 3\r\n c: 'c2'\r\n d: true\r\n}\r\n\r\ntype Case3Answer = {\r\n a: 3\r\n b: {\r\n b: 'b'\r\n }\r\n c: 'c2'\r\n d: true\r\n}\r\n\r\n// case 4\r\ntype Case4Target = {\r\n a: 1\r\n b: ['b']\r\n}\r\n\r\ntype Case4Answer = {\r\n a: 1\r\n b: ['b']\r\n}\r\n\r\ntype cases = [\r\n Expect<Equal<Assign<Case1Target, [Case1Origin1, Case1Origin2, Case1Origin3]>, Case1Answer>>,\r\n Expect<Equal<Assign<Case2Target, [Case2Origin1, Case2Origin2]>, Case2Answer>>,\r\n Expect<Equal<Assign<Case3Target, [Case3Origin1, Case3Origin2]>, Case3Answer>>,\r\n Expect<Equal<Assign<Case4Target, ['', 0]>, Case4Answer>>,\r\n]\r\n"}]