type-challengesの学習記録

Tuple to Object(初級)

First of Array(初級)

Awaited(初級)

回答
これでは不正解
type MyAwaited<T> = T extends Promise<infer U> ? U : never;

回答
type MyAwaited<T> = T extends PromiseLike<infer U> ? U extends PromiseLike<any> ? MyAwaited<U> : U : never;

Promise
だけなら以下でもOK
type MyAwaited<T> = T extends Promise<infer U> ? U extends Promise<any> ? MyAwaited<U> : U : never;

Concat(初級)

回答
type Concat<T extends readonly any[], U extends readonly any[]> = [...T, ...U];

Includes(初級)

これだと不完全
type Includes<T extends readonly any[], U> = U extends T[number] ? true : false;

回答
完全一致は一癖ある。
type MyEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
type Includes<T extends readonly any[], U> = T extends [infer X, ...infer Y]
? MyEqual<U, X> extends true
? true
: Includes<Y, U>
: false;

Parameters(初級)

回答
type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer X) => any ? X : never;
なぜタプル型が返るか?
ChatGPT先生による解説:
関数の引数型は、関数のシグネチャを記述する際に、すべての引数の型を タプル型 としてまとめて表現します

Get Return Type(中級)

回答
type MyReturnType<T> = T extends ((...args: any) => infer X) ? X : never;

Omit(中級)

Readonly 2(中級)

回答
なんか違う。。。
type MyReadonly2<T, K = keyof T> = {
[t in keyof T as t extends K ? never : t]: T[t];
} & {
readonly [t in keyof T as t extends K ? t : never]: T[t];
};

回答
Kの指定方法の違い。
type MyReadonly2<T, K extends keyof T = keyof T> = {
[t in keyof T as t extends K ? never : t]: T[t];
} & {
readonly [t in keyof T as t extends K ? t : never]: T[t];
};

Deep Readonly(中級)

回答
type DeepReadonly<T> = {
readonly [t in keyof T]: T[t] extends Object ? T[t] extends Function ? T[t] : DeepReadonly<T[t]> : T[t];
};

Chainable Options

回答
チェインを繋げるために自分自身を返す必要がある。
type Chainable<T = {}> = {
option<K extends string, V extends any>(key: K extends keyof T ? never : K, value: V):
Chainable<{
[t in keyof T as t extends K ? never : t]: T[t]
} & {
[k in K]: V
}>
get(): T
}

Last of Array

回答
JSと使い勝手が違うかも。
type Last<T extends any[]> = T extends [...args: any, arg: infer X] ? X : never;

Pop(中級)

回答
先ほどの類題。
type Pop<T extends any[]> = T extends [...args: infer X, arg: any] ? X : [];

Promise.all(中級)

回答途中
declare function PromiseAll<A extends any[]>(values: A): A extends [arg: infer X, ...args: infer Y];

回答
これだと不完全。
declare function PromiseAll<A extends any[]>(values: A): Promise<{
[a in keyof A]: Awaited<A[a]>;
}>;

回答
declare function PromiseAll<A extends any[]>(values: readonly [...A]): Promise<{
[a in keyof A]: Awaited<A[a]>;
}>;

Type Lookup(中級)

回答
type LookUp<U extends Cat | Dog, T extends "cat" | "dog"> = U extends {type: T} ? U : never;

Trim Left(中級)

回答
type TrimLeft<S extends string> = S extends `${' ' | '\n' | '\t'}${infer T}` ? TrimLeft<T> : S;

Trim(中級)

回答
type Trim<S extends string> = S extends `${' ' | '\n' | '\t'}${infer T}`
? Trim<T>
: S extends `${infer T}${' ' | '\n' | '\t'}` ? Trim<T> : S;

Capitalize(中級)

回答
type MyCapitalize<S extends string> = S extends `${infer X}${infer Y}` ? `${Uppercase<X>}${Y}` : '';

Replace(中級)

回答
type Replace<S extends string, From extends string, To extends string> =
From extends ''
? S
: S extends `${From}${infer Y}`
? `${To}${Y}`
: S extends `${infer X}${From}${infer Y}`
? `${X}${To}${Y}`
: S extends `${infer X}${From}`
? `${X}${To}`
: S;

回答
無駄な処理を省くと以下になる。
type Replace<S extends string, From extends string, To extends string> =
From extends ''
? S
: S extends `${infer X}${From}${infer Y}`
? `${X}${To}${Y}`
: S;

ReplaceAll(中級)

回答
type ReplaceAll<S extends string, From extends string, To extends string> =
From extends ''
? S
: S extends `${infer X}${From}${infer Y}`
? `${X}${To}${ReplaceAll<`${Y}`, From, To>}`
: S;

Append Argument(中級)

回答
type AppendArgument<Fn extends Function, A extends any> =
Fn extends (...args: infer X) => infer Y
? (...args: [...X, A]) => Y
: never;

Permutation(中級)

Length of String(中級)

回答
type LengthOfString<S extends string, L = []> =
L extends any[]
? S extends `${S[0]}${infer Y}`
? LengthOfString<Y, [...L, S[0]]>
: L['length']
: never;

Flatten(中級)

回答
type Flatten<S extends any[], T = []> =
T extends any[]
? S extends [S[0], ...args: infer X]
? S[0] extends any[]
? Flatten<[...S[0], ...X], T>
: Flatten<X, [...T, S[0]]>
: T
: never;

回答
type Flatten<S extends any[], T extends any[] = []> =
S extends [S[0], ...args: infer X]
? S[0] extends any[]
? Flatten<[...S[0], ...X], T>
: Flatten<X, [...T, S[0]]>
: T;

Append to object(中級)

回答
type AppendToObject<T extends Object, U extends string, V extends any> = {
[X in keyof T | U]: X extends keyof T ? T[X] : V;
};

Absolute(中級)

回答
BigIntでも対応できるのは面白い!
type Absolute<T extends number | string | bigint> = `${T}` extends `-${infer X}` ? X : `${T}`;

String to Union(中級)

回答
特にひねりなし
type StringToUnion<T extends string> = T extends `${infer X}${infer Y}` ? X | StringToUnion<Y> : never;

Merge(中級)

回答
type Merge<F extends Object, S extends Object> = {
[X in keyof (F & S)]: X extends keyof S ? S[X] : X extends keyof F ? F[X] : never;
};

KebabCase(中級)

回答
type KebabCase<S extends string> =
S extends `${infer X}${infer Y}`
? Y extends Uncapitalize<Y>
? `${Uncapitalize<X>}${KebabCase<Y>}`
: `${Uncapitalize<X>}-${KebabCase<Y>}`
: S;

別解
type KebabCase<S extends string> =
S extends `${infer X}${infer Y}`
? Y extends Uncapitalize<Y>
? `${Lowercase<X>}${KebabCase<Y>}`
: `${Lowercase<X>}-${KebabCase<Y>}`
: S;

Diff(中級)

回答
type Diff<O extends Object, O1 extends Object> = {
[o in keyof (O & O1) as o extends keyof O
? o extends keyof O1
? never
: o
: o extends keyof O1
? o
: never
]: o extends keyof O ? O[o] : o extends keyof O1 ? O1[o] : never;
}

AnyOf(中級)

回答
type AnyOf<T extends readonly any[]> =
T extends []
? false
: T extends [infer X, ...args: infer Y]
? X extends (false | null | undefined | 0 | '' | [] | {[key: string]: never})
? AnyOf<Y>
: true
: false;

IsNever (中級)

IsUnion(中級)

ReplaceKeys(中級)

回答
type ReplaceKeys<U, T, Y> = {
[u in keyof U]:
u extends T
? u extends keyof Y
? Y[u]
: never
: U[u];
};

Remove Index Signature(中級)

回答
type RemoveIndexSignature<T> = {
[t in keyof T as string extends t ? never : number extends t ? never : symbol extends t ? never : t]: T[t];
}

Percentage Parser(中級)

回答
愚直に実装
type PercentageParser<A extends string> =
A extends `${infer X}${infer Y}`
? X extends "+" | "-"
? A extends `${X}${infer Y}${"%"}`
? [X, Y, "%"]
: [X, Y, ""]
: A extends `${infer Y}${"%"}`
? ["", Y, "%"]
: ["", A, ""]
: ["", "", ""];

Drop Char(中級)

回答
type DropChar<S extends string, C extends string, T extends string = ""> =
S extends `${infer X}${infer Y}`
? X extends C
? DropChar<Y, C, T>
: DropChar<Y, C, `${T}${X}`>
: T;

MinusOne(中級)

回答
配列の限界?で1000までしか不可。
type MinusOne<T extends number, C extends any[] = [1]> =
T extends C["length"]
? C extends [infer X, ...args: infer Y]
? [...Y]["length"]
: C["length"]
: MinusOne<T, [1, ...C,]>;

途中
type MinusOne<T extends number, C extends any[] = []> =
`${T}` extends `${infer X extends number}${infer Y extends number}`
? MinusOne<Y, [...C, X]>
: C extends [...args: infer X extends number[], arg: infer Y extends number]
? Y extends 0
? MyMinusOne<Y>
: `${Flat<X>}${MyMinusOne<Y>}` extends infer Z extends number
? Z
: never
: never;

1001以上の対応は難しいのでパス。

PickByType(中級)

回答
type PickByType<T extends Object, U> = {
[t in keyof T as T[t] extends U ? t : never]: T[t];
}

StartsWith(中級)

回答
type StartsWith<T extends string, U extends string> =
T extends U
? true
: T extends `${infer X extends string}${U}${infer Y extends string}`
? true
: false;

EndsWith(中級)

回答
StartsWithと同じもので可能
type EndsWith<T extends string, U extends string> =
T extends U
? true
: T extends `${infer X extends string}${U}${infer Y extends string}`
? true
: false;

PartialByKeys(中級)

回答
&のままではだめなので、マージする必要がある。
type PartialByKeys<T extends Object, K extends keyof T = keyof T> = {
[t in keyof T as t extends K ? never : t]: T[t];
} & {
[k in K]?: T[k];
} extends infer X ? {[x in keyof X]: X[x]} : never;

別解
type PartialByKeys<T extends Object, K extends keyof T = keyof T> = {
[t in keyof Omit<T, K>]: T[t];
} & {
[k in K]?: T[k];
} extends infer X ? {[x in keyof X]: X[x]} : never;

RequiredByKeys(中級)

回答
type RequiredByKeys<T extends Object, K extends keyof T = keyof T> = {
[t in keyof Omit<T, K>]: T[t];
} & {
[k in K]-?: T[k];
} extends infer X ? {[x in keyof X]: X[x]} : never;

OmitByType(中級)

回答
type OmitByType<T extends object, U> = {
[t in keyof T as T[t] extends U ? never : t]: T[t];
}

ObjectEntries(中級)

回答
type ObjectEntries<T extends object> =
Required<T> extends infer X extends T
? {[t in keyof X]: [t, [X[t]] extends [never] ? undefined : X[t]]}[keyof T]
: never;

Shift(中級)

回答
type Shift<T extends any[]> = T extends [arg: infer X, ...args: infer Y] ? [...Y] : [];

Tuple to Nested Object(中級)

回答
type TupleToNestedObject<T extends any[], U> =
T extends [arg: infer X extends string, ...args: infer Y extends any[]]
? {
[x in `${X}`]: Y extends [] ? U : TupleToNestedObject<Y, U>;
}
: U;

Reverse(中級)

回答
type Reverse<T extends any[]> = T extends [...args: infer Y, arg: infer X] ? [X, ...Reverse<Y>] : [];

Flip Arguments(中級)

回答
先ほどのReverseを活用。
type Reverse<T extends any[]> = T extends [...args: infer Y, arg: infer X] ? [X, ...Reverse<Y>] : [];
type FlipArguments<T extends (...args: any) => any> = T extends (...args: infer X extends any[]) => infer Y ? (...args: Reverse<X>) => Y : never;

FlattenDepth(中級)

回答途中
type FlattenOne<S extends any[]> =
S extends [S[0], ...args: infer X]
? S[0] extends any[]
? [...S[0], ...X]
: [S[0], ...FlattenOne<[...X]>]
: S;
type MinusOne<T extends string> =
T extends `${infer X extends number}${infer Y extends string}`
? Y extends ""
? ["9", "0", "1", "2", "3", "4", "5", "6", "7", "8"][X]
: Y extends "0"
? `${MinusOne<`${X}`>}${MinusOne<Y>}`
: `${X}${MinusOne<Y>}`
: never;
type FlattenDepth<T extends any[], U extends number = 1> =
U extends 1
? FlattenOne<T>
: T extends FlattenOne<T>
? T
: MinusOne<`${U}`> extends `${infer X extends number}`
? FlattenDepth<FlattenOne<T>, X>
: never;

回答
だいぶ無理やり減算処理を実現。
※合っているかは不明(とりあえず今回の問題はクリアした)
※110->9になるため、MinusOneは間違っている
type FlattenOne<S extends any[]> =
S extends [S[0], ...args: infer X]
? S[0] extends any[]
? [...S[0], ...FlattenOne<[...X]>]
: [S[0], ...FlattenOne<[...X]>]
: S;
type MinusOne<T extends string> =
T extends `${infer X extends number}${infer Y extends string}`
? Y extends ""
? ["9", "0", "1", "2", "3", "4", "5", "6", "7", "8"][X]
: Y extends "0"
? `${MinusOne<`${X}`>}${MinusOne<Y>}` extends `0${infer A}`
? `${A}`
: `${MinusOne<`${X}`>}9`
: `${X}${MinusOne<Y>}` extends `${X}9${infer Z}`
? `${Y}` extends `9${infer A}`
? `${X}9${Z}`
: `${MinusOne<`${X}`>}9${Z}` extends `0${infer A}`
? `${A}`
: `${MinusOne<`${X}`>}9${Z}`
: `${X}${MinusOne<Y>}`
: never;
type FlattenDepth<T extends any[], U extends number = 1> =
U extends 1
? FlattenOne<T>
: T extends FlattenOne<T>
? T
: MinusOne<`${U}`> extends `${infer X extends number}`
? FlattenDepth<FlattenOne<T>, X>
: never;

BEM style string(中級)

回答
type BEM<B extends string, E extends string[], M extends string[]> =
E extends [infer X extends string, ...infer Y extends string[]]
? BEM<`${B}__${X}`, [...Y], M>
: M extends [infer X extends string, ...infer Y extends string[]]
? Exclude<`${B}--${X}` | BEM<B, E, [...Y]>, B>
: B;

InorderTraversal(中級)

回答
左の要素は左に、右の要素は右に配置。
type InorderTraversal<T extends TreeNode | null> =
T extends TreeNode
? T["left"] extends TreeNode
? [...InorderTraversal<T["left"]>, T["val"]]
: T["right"] extends TreeNode
? [T["val"], ...InorderTraversal<T["right"]>]
: [T["val"]]
: []

Flip(中級)

回答
type Flip<T extends object> = {
[t in keyof T as T[t] extends (string | number | boolean) ? `${T[t]}` : never]: t;
};

Fibonacci Sequence(中級)

回答
type Fibonacci<T extends number, A extends any[] = [1], B extends any[] = [1], C extends any[] = [1, 1, 1]> =
T extends 1 | 2
? 1
: C["length"] extends T
? [...A, ...B]["length"]
: Fibonacci<T, B, [...A, ...B], [...C, 1]>;

文字の組み合わせ(中級)

回答
type AllCombinations<S extends string, T extends string = ""> =
S extends `${infer X}${infer Y}`
? `${X}${AllCombinations<`${Y}${T}`>}` | `${AllCombinations<`${Y}`, `${T}${X}`>}`
: '';

Greater Than(中級)

回答
Union型を作成し、上の桁から比較。
不一致または桁数が異なる時に最終判定。
type Split<T extends (string | number)> =
`${T}` extends `${infer X extends number}${infer Y extends string}`
? [X, ...Split<Y>]
: [];
type GetUnion<T extends number, U extends any[] = []> =
T extends U["length"]
? [U["length"], ...U][number]
: GetUnion<T, [...U, U["length"]]>;
type GreaterThanAll<T extends number[], U extends number[]> =
GetUnion<T["length"]> extends GetUnion<U["length"]>
? GetUnion<U["length"]> extends GetUnion<T["length"]>
? T extends [infer X extends number, ...infer Y extends number[]]
? U extends [infer A extends number, ...infer B extends number[]]
? GetUnion<X> extends GetUnion<A>
? GetUnion<A> extends GetUnion<X>
? GreaterThanAll<Y, B>
: false
: true
: true
: false
: false
: true;
type GreaterThan<T extends number, U extends number> = GreaterThanAll<Split<T>, Split<U>>

Zip(中級)

回答
type Zip<T extends any[], U extends any[]> =
T extends [infer X, ...infer Y]
? U extends [infer A, ...infer B]
? [[X, A], ...Zip<Y, B>]
: []
: [];

IsTuple(中級)

回答
type IsTuple<T> =
[T] extends [never]
? false
: T extends any[] | readonly any[]
? any[] extends T
? false
: true
: false;

Chunk(中級)

回答
type Chunk<T extends any[], U extends number, R extends any[] = []> =
T extends [infer X, ...infer Y]
? R["length"] extends U
? [[...R], ...Chunk<Y, U, [X]>]
: [...Chunk<Y, U, [...R, X]>]
: [[...R]] extends [[]]
? []
: [[...R]];

Fill(中級)

回答
Lの値で分岐。
type Fill<
T extends unknown[],
N,
Start extends number = 0,
End extends number = T['length'],
L extends number[] = [],
> =
T[L["length"]] extends undefined
? []
: L["length"] extends Start
? L["length"] extends End
? [T[L["length"]], ...Fill<T, N, Start, End, [1, ...L]>]
: [N, ...Fill<T, N, Start, End, [2, ...L]>]
: L extends [infer X extends number, ...infer Y]
? X extends 2
? L["length"] extends End
? [T[L["length"]], ...Fill<T, N, Start, End, [1, ...L]>]
: [N, ...Fill<T, N, Start, End, [2, ...L]>]
: [T[L["length"]], ...Fill<T, N, Start, End, [1, ...L]>]
: [T[L["length"]], ...Fill<T, N, Start, End, [1, ...L]>];

Trim Right(中級)

回答
Trimの類題。
type TrimRight<S extends string> = S extends `${infer T}${" " | "\n" | "\t"}` ? TrimRight<T> : S;

Without(中級)

回答
type Without<T extends number[], U extends number | number[]> =
T extends [infer X, ...infer Y extends number[]]
? U extends number[]
? X extends U[number]
? [...Without<Y, U>]
: [X, ...Without<Y, U>]
: X extends U
? [...Without<Y, U>]
: [X, ...Without<Y, U>]
: [];

Trunc(中級)

回答
type Trunc<T extends string | number> =
`${T}` extends `${infer X}.${infer Y}`
? X extends "-" | ""
? `${X}0`
: X
: `${T}`;

IndexOf(中級)

回答
anyの判定はkeyof
type IndexOf<T extends any[], U extends any, L extends number[] = []> =
T extends [infer X, ...infer Y]
? X extends U
? U extends X
? keyof X extends keyof U
? keyof U extends keyof X
? L["length"]
: IndexOf<Y, U, [...L, 1]>
: IndexOf<Y, U, [...L, 1]>
: IndexOf<Y, U, [...L, 1]>
: IndexOf<Y, U, [...L, 1]>
: -1;

Join(中級)

回答
type Join<T extends string[], U extends (string | number) = ","> =
T extends [infer X extends string, ...infer Y extends string[]]
? `${X}${U}${Join<Y, U>}` extends `${infer A}`
? A extends `${infer B}${U}`
? B
: A
: never
: "";

LastIndexOf (中級)

回答
だいぶ力技パターン。
type IndexOf<T extends any[], U extends any, L extends number[] = []> =
T extends [infer X, ...infer Y]
? X extends U
? U extends X
? keyof X extends keyof U
? keyof U extends keyof X
? L["length"]
: IndexOf<Y, U, [...L, 1]>
: IndexOf<Y, U, [...L, 1]>
: IndexOf<Y, U, [...L, 1]>
: IndexOf<Y, U, [...L, 1]>
: -1;
type Reverse<T extends any[]> = T extends [...args: infer Y, arg: infer X] ? [X, ...Reverse<Y>] : [];
type Pop<T extends any[], U extends number, L extends number[] = []> =
U extends L["length"]
? T
: T extends [...infer X, infer Y]
? Pop<X, U, [1, ...L]>
: [];
type LastIndexOf<T extends any[], U extends any> =
IndexOf<Reverse<T>, U> extends infer X extends number
? X extends -1
? -1
: Pop<Pop<T, X>, 1>["length"]
: never;

Unique(中級)

回答
IndexOfにnever判定を追加して実施。
type IndexOf<T extends any[], U extends any, L extends number[] = []> =
T extends [infer X, ...infer Y]
? [X] extends [U]
? [U] extends [X]
? keyof X extends keyof U
? keyof U extends keyof X
? L["length"]
: IndexOf<Y, U, [...L, 1]>
: IndexOf<Y, U, [...L, 1]>
: IndexOf<Y, U, [...L, 1]>
: IndexOf<Y, U, [...L, 1]>
: -1;
type Unique<T extends any[], L extends any[] = []> =
T["length"] extends 0
? L
: T extends [T[0], ...infer X]
? IndexOf<L, T[0]> extends -1
? [...Unique<X, [...L, T[0]]>]
: [...Unique<X, L>]
: [...Unique<[], [...L, T[0]]>];

MapTypes(中級)

回答
type MapTypes<T extends object, R extends { mapFrom: any, mapTo: any }> = {
[t in keyof T]: T[t] extends R["mapFrom"]
? R extends { mapFrom: T[t]}
? R["mapTo"]
: never
: T[t];
};

Construct Tuple(中級)

回答
type ConstructTuple<L extends number, U extends unknown[] = []> =
U["length"] extends L
? U
: ConstructTuple<L, [...U, unknown]>;

Number Range(中級)

回答
type NumberRange<L extends number, H extends number, T extends number[] = [], U extends number[] = []> =
U["length"] extends 0
? T["length"] extends L
? NumberRange<L, H, [1, ...T], [...U, L]>
: NumberRange<L, H, [1, ...T], U>
: T["length"] extends H
? [...U, T["length"]][number]
: NumberRange<L, H, [1, ...T], [...U, T["length"]]>;

Combination(中級)

回答
他の人の回答を参考にしたが、難しい。
type Combination<T extends string[], U extends string = T[number], K extends string = U> =
K extends U
? K | `${K} ${Combination<T, Exclude<U, K>>}`
: never;

Subsequence (中級)

回答
type Subsequence<T extends any[], U extends any[] = []> =
T extends [infer X, ...infer Y]
? Subsequence<Y, [...U, X] | U>
: U;

CheckRepeatedChars(中級)

回答
type CheckRepeatedChars<T extends string> =
T extends `${infer X}${infer Y}`
? Y extends `${infer A}${X}${infer B}`
? true
: CheckRepeatedChars<Y>
: false;

FirstUniqueCharIndex(中級)

回答
type Find<T extends string, U extends string> =
T extends `${infer X}${infer Y}`
? X extends U
? true
: Find<Y, U>
: false;
type Count<T extends string, U extends any[] = []> = T extends `${infer X}${infer Y}` ? Count<Y, [...U, 1]> : U['length'];
type FirstUniqueCharIndex<T extends string, U extends string = ''> =
T extends `${infer X}${infer Y}`
? Find<Y, X> extends true
? FirstUniqueCharIndex<Y, `${U}${X}`>
: Find<U, X> extends true
? FirstUniqueCharIndex<Y, `${U}${X}`>
: Count<U>
: -1;

Parse URL Params(中級)

回答
type Split<T extends string, U extends string, S extends any[] = []> =
T extends `${infer X}${U}${infer Y}`
? Split<Y, U, [...S, X extends `:${infer Z}` ? Z : never]>
: T extends `:${infer Z}`
? [...S, Z][number]
: S[number];
type ParseUrlParams<T extends string> = Split<T, '/'>;

GetMiddleElement(中級)

回答
type GetMiddleElement<T extends any[]> =
T['length'] extends 0 | 1 | 2
? T
: GetMiddleElement<T extends [infer X, ...infer Y, infer Z] ? Y : []>;

Appear only once(中級)

回答
type Find<T extends any[], U extends any> =
T extends [infer X, ...infer Y]
? U extends X
? X extends U
? true
: Find<Y, U>
: Find<Y, U>
: false;
type FindEles<T extends any[], U extends any[] = [], S extends any[] = []> =
T extends [infer X, ...infer Y]
? Find<[...Y, ...U, ...S], X> extends true
? FindEles<Y, U, [...S, X]>
: FindEles<Y, [...U, X], S>
: U;

Count Element Number To Object(中級)

回答
type Flatten<S extends any[], T extends any[] = []> =
S extends [S[0], ...args: infer X]
? S[0] extends any[]
? Flatten<[...S[0], ...X], T>
: Flatten<X, [...T, S[0]]>
: T;
type Count<T extends any[], U extends any, S extends any[] = []> =
T extends [infer X, ...infer Y]
? X extends U
? Count<Y, U, [...S, 1]>
: Count<Y, U, S>
: S['length'];
type CountElementNumberToObject<T extends any[]> =
Flatten<T> extends infer X extends any[]
? {
[x in X[number]]: Count<X, x>;
}
: never;

Integer(中級)

回答
type Integer<T extends any> =
T extends number
? number extends T
? never
: `${T}` extends `${infer X extends number}.${infer Y extends number}`
? Y extends 0
? X
: never
: T
: never;

ToPrimitive(中級)

回答
他者の回答を参考。
valueOfメソッドの有無とその戻り値の型を使って判別。
type ToPrimitive<T extends any> =
T extends object
? T extends (...args: any) => any
? Function
: { [t in keyof T]: ToPrimitive<T[t]> }
: T extends { valueOf: () => infer X }
? X
: T;

DeepMutable(中級)

回答
type DeepMutableCore<T> =
T extends object
? T extends (...args: any) => any
? T
: { -readonly [t in keyof T]: DeepMutableCore<T[t]> }
: T;
type DeepMutable<T extends object> = DeepMutableCore<T>;

All (中級)

回答
type AllCore<T extends any[], U extends any> =
T extends [infer X, ...infer Y]
? X extends U
? U extends X
? keyof X extends keyof U
? keyof U extends keyof X
? AllCore<Y, U>
: false
: false
: false
: false
: true;
type All<T extends any[], U extends any> =
T extends [never]
? [U] extends [never]
? true
: false
: AllCore<T, U>;

Filter(中級)

回答
type Filter<T extends any[], P extends any, S extends any[] = []> =
T extends [infer X, ...infer Y]
? X extends P
? Filter<Y, P, [...S, X]>
: Filter<Y, P, S>
: S;

FindAll(中級)

type Count<T extends string, U extends any[] = []> = T extends `${infer X}${infer Y}` ? Count<Y, [...U, 1]> : U['length'];
type FindAll<T extends string, P extends string, S extends any[] = [], R extends string = ''> =
P extends ''
? S
: T extends `${infer X extends string}${P}${infer Y}`
? `${P}${Y}` extends `${infer A}${infer B}`
? FindAll<B, P, [...S, Count<`${R}${X}`>], `${R}${X}${A}`>
: S
: S;

Combination key type(中級)

回答
他者の回答あり。
type Combs<T extends any[], U = never> =
T extends [infer X extends string, ...infer Y extends string[]]
? Combs<Y, U | `${X} ${Y[number]}`>
: U;

Permutations of Tuple(中級)

回答
他者回答の参考。
type PermutationsOfTuple<T extends unknown[], S extends any[] = []> =
T extends []
? []
: T['length'] extends S['length']
? never
: T extends [infer X, ...infer Y]
? [X, ...PermutationsOfTuple<Y>] | PermutationsOfTuple<[...Y, X], [...S, X]>
: never;

Replace First(中級)

回答
type ReplaceFirst<T extends readonly unknown[], S, R, U extends any[] = []> =
T extends [infer X, ...infer Y]
? X extends S
? [...U, R, ...Y]
: ReplaceFirst<Y, S, R, [...U, X]>
: U;

Transpose(中級)

回答
type Init<T extends any[] = [], U extends number = 0> =
T['length'] extends U
? T
: Init<[...T, []], U>;
type TransposeCore<T extends any[][], U extends any[], L extends any[] = []> =
U[L['length']] extends undefined
? []
: T[L['length']] extends undefined
? [[U[L['length']]], ...TransposeCore<T, U, [...L, 1]>]
: [[...T[L['length']], U[L['length']]], ...TransposeCore<T, U, [...L, 1]>]
type Transpose<M extends number[][], L extends any[][] = []> =
M['length'] extends 0
? L
: M extends [infer X extends any[], ...infer Y extends any[][]]
? L extends []
? Init<L, X['length']> extends infer Z extends any[][]
? Transpose<Y, TransposeCore<Z, X> extends infer A extends any[][] ? A : never>
: never
: Transpose<Y, TransposeCore<L, X> extends infer A extends any[][] ? A : never>
: L;

JSON Schema to TypeScript(中級)

途中
type JSONSchema2TS<T extends {type?: any, enum?: any, properties?: any, items?: any, required?: string[]}> =
T['enum'] extends any[]
? T['enum'][number]
: T['type'] extends 'string'
? string
: T['type'] extends 'number'
? number
: T['type'] extends 'boolean'
? boolean
: T['type'] extends 'object'
? T['properties'] extends object
? {
[t in keyof T['properties']]?: JSONSchema2TS<T['properties'][t]>;
}
: Record<string, unknown>
: T['type'] extends 'array'
? T['items'] extends object
? JSONSchema2TS<T['items']>[]
: unknown[]
: never;

回答
Omitだけ参考。
type JSONSchema2TS<T extends {type?: any, enum?: any, properties?: any, items?: any, required?: string[]}> =
T['enum'] extends any[]
? T['enum'][number]
: T['type'] extends 'string'
? string
: T['type'] extends 'number'
? number
: T['type'] extends 'boolean'
? boolean
: T['type'] extends 'object'
? T['properties'] extends object
? T['required'] extends string[]
? Omit<{
[t in T['required'][number]]: JSONSchema2TS<T['properties'][t]>
} & {
[t in keyof T['properties']]?: JSONSchema2TS<T['properties'][t]>
}, never>
: {
[t in keyof T['properties']]?: JSONSchema2TS<T['properties'][t]>;
}
: Record<string, unknown>
: T['type'] extends 'array'
? T['items'] extends object
? JSONSchema2TS<T['items']>[]
: unknown[]
: never;

Square(中級)

回答
配列限界のため、100以上のケースは無理。
が、これ以上は沼なのでやらない。
type LengthArray<T extends number, L extends number[] = []> =
L['length'] extends T
? L
: LengthArray<T, [...L, 1]>;
type SquareCore<T extends number[], U extends number, L extends number[] = [], S extends number[] = []> =
U extends L['length']
? S['length']
: SquareCore<T, U, [...L, 1], [...T, ...S]>;
type Square<N extends number> =
`${N}` extends `-${infer X extends number}`
? LengthArray<X> extends infer Y extends number[]
? SquareCore<Y, X>
: never
: LengthArray<N> extends infer X extends number[]
? SquareCore<X, N>
: never;

Triangular number(中級)

回答
先ほどの処理を流用。
type LengthArray<T extends number, L extends number[] = []> =
L['length'] extends T
? L
: LengthArray<T, [...L, 1]>;
type TriangularCore<T extends number[], U extends number, L extends number[] = []> =
U extends L['length']
? T['length']
: TriangularCore<[...T, ...L], U, [...L, 1]>;
type Triangular<N extends number> = TriangularCore<LengthArray<N>, N>;

CartesianProduct(中級)

回答
分配の問題。
type CartesianProduct<T, U> =
T extends T
? U extends U
? [T, U]
: never
: never;

MergeAll(中級)

回答
type MergeAll<XS extends any[], S extends object = {}> =
XS extends [infer X extends object, ...infer Y extends object[]]
? {
[x in keyof X]: X[x];
} extends infer Z
? MergeAll<Y, {
[x in keyof Z | keyof S]:
x extends keyof S
? x extends keyof Z
? S[x] | Z[x]
: S[x]
: x extends keyof Z
? Z[x]
: never;
}>
: never
: S

CheckRepeatedTuple(中級)

回答
type MyEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
type Find<T extends any[], U extends any> =
T extends [infer X, ...infer Y]
? MyEqual<X, U> extends true
? true
: Find<Y, U>
: false;
type CheckRepeatedTuple<T extends unknown[]> =
T extends [infer X, ...infer Y]
? Find<Y, X> extends true
? true
: CheckRepeatedTuple<Y>
: false;

Public Type(中級)

回答
type PublicType<T extends object> = {
[t in keyof T as t extends string ? `${t}` extends `_${infer X}` ? never : t : never]: T[t];
};

ExtractToObject(中級)

回答
type ExtractToObject<T extends object, U extends keyof T> = {
[t in keyof T as t extends U ? t : never]: T[t];
} extends { [K: string]: infer X } ? Omit<{
[x in keyof X]: X[x];
} & {
[t in keyof T as t extends U ? never : t]: T[t];
}, never> : never;

Deep Omit(中級)

回答
type DeepOmit<T extends object, S extends string> =
S extends `${infer X extends string}.${infer Y extends string}`
? {
[t in keyof T]: t extends X ? DeepOmit<{
[t in keyof T as t extends X ? t : never]: T[t];
} extends {[K:string]: infer Z extends object} ? Z : never, Y> : T[t];
}
: Omit<T, S>;

IsOdd(中級)

回答
type IsOdd<T extends number> =
`${T}` extends `${infer X}.${infer Y}`
? false
: `${T}` extends `${infer A}e${infer B}`
? false
: `${T}` extends `${infer X}${1 | 3 | 5 | 7 | 9}` ? true : false;

Tower of hanoi(中級)

回答
type Length<T extends number, S extends any[] = []> =
T extends S['length']
? S
: Length<T, [1, ...S]>;
type Hanoi<N extends number, From = 'A', To = 'B', Intermediate = 'C'> = HanoiCore<N, From, To, Intermediate>
type HanoiCore<T extends number, From = 'A', To = 'B', Intermediate = 'C', S extends number[] = []> =
T extends 0
? []
: [
...HanoiCore<Length<T> extends [infer X, ...infer Y] ? Y['length'] : never, From, Intermediate, To>,
[From, To],
...HanoiCore<Length<T> extends [infer X, ...infer Y] ? Y['length'] : never, Intermediate, To, From>
];

Pascal's triangle(中級)

あとで

途中回答
type Sum<T extends number, S extends number> = [...GetArray<T>, ...GetArray<S>]['length'];
type GetArray<T extends number, L extends any[] = []> =
T extends L['length']
? L
: GetArray<T, [...L, 1]>;
type GetTail<T extends any[]> =
T extends [...infer X, infer Y]
? Y
: T[0];
type PascalCoreLoop<T extends any[], L extends any[] = []> =
T extends undefined
? 1
: T['length'] extends L['length']
? []
: [PascalCore<T, L['length']>, ...PascalCoreLoop<T, [1, ...L]>];
type PascalCore<T extends any[], L extends number> =
T extends undefined
? 1
: Sum<T[L], T[Sum<L, 1> extends infer X extends number ? X : T['length']] extends infer X extends number ? X : 0>
type Pascal<N extends number, L extends any[] = []> =
N extends L['length']
? L
: Pascal<N, [...L, PascalCoreLoop<GetTail<L>>]>

回答
type Sum<T extends number, S extends number> = [...GetArray<T>, ...GetArray<S>]['length'];
type GetArray<T extends number, L extends any[] = []> =
T extends L['length']
? L
: GetArray<T, [...L, 1]>;
type GetTail<T extends any[]> =
T extends [...infer X, infer Y]
? Y
: T[0];
type PascalCoreLoop<T extends any[], L extends any[] = []> =
T extends undefined
? []
: L['length'] extends Sum<T['length'], 0>
? []
: [PascalCore<T, L['length']>, ...PascalCoreLoop<T, [1, ...L]>];
type PascalCore<T extends any[], L extends number> =
T extends undefined
? 1
: Sum<T[L], T[Sum<L, 1> extends infer X extends number ? X : T['length']] extends infer X extends number ? X : 0>;
type Pascal<N extends number, L extends any[] = []> =
N extends L['length']
? L
: Pascal<N, [...L, [1, ...PascalCoreLoop<GetTail<L>>]]>;

IsFixedStringLiteralType(中級)

途中回答
'ABC' | 'DEF'の場合に不可。
type IsBoolean<T extends string> =
[T] extends [`${true}`]
? true
: [T] extends [`${false}`]
? true
: false;
type IsNever<T extends string> =
[T] extends [never]
? true
: false;
type IsPrimitive<T extends string> =
`${string}` extends T
? true
: `${number}` extends T
? true
: `${bigint}` extends T
? true
: `${boolean}` extends T
? true
: false;
type IsFixedStringLiteralType<S extends string> =
IsNever<S> extends true
? false
: [S]extends [`${infer X}${boolean}${infer Y}`]
? [`${X}${boolean}${Y}`] extends [S]
? false
: true
: S extends `${infer X}${infer Y}`
? IsFixedStringLiteralTypeCore<X> extends false
? false
: IsFixedStringLiteralType<Y>
: IsFixedStringLiteralTypeCore<S>;
type IsFixedStringLiteralTypeCore<S extends string> =
true extends IsNever<S>
? false
: true extends IsBoolean<S>
? true
: true extends IsPrimitive<S>
? false
: true;

回答
他者回答を参考
type MyEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
type IsFixedStringLiteralType<S extends string> =
{} extends Record<S, 1>
? false
: MyEqual<[S], S extends S ? [S] : never>;

Compare Array Length(中級)

回答
type CompareArrayLength<T extends any[], U extends any[]> =
T['length'] extends U['length']
? 0
: T['length'] extends 0
? -1
: U['length'] extends 0
? 1
: CompareArrayLength<T extends [infer _, ...infer X] ? X : never, U extends [infer _, ...infer Y] ? Y : never>;

Defined Partial Record(中級)

回答
type DefinedPartial<T extends object, P extends keyof T = keyof T> =
P extends keyof T
? T | DefinedPartial<Omit<T, P>>
: never;

Longest Common Prefix(中級)

回答
type Reverse<T extends string, S extends string = ""> =
T extends ""
? S
: T extends `${infer X}${infer Y}`
? Reverse<Y, `${X}${S}`>
: never;
type LongestCommonPrefixCore<T extends string, S extends string, L extends string = ""> =
T extends ""
? ""
: S extends ""
? ""
: S extends `${infer _}${T}`
? Reverse<T>
: LongestCommonPrefixCore<T extends `${infer X}${infer Y}` ? `${Y}` : never, S>;
type LongestCommonPrefix<T extends string[], P extends string = ''> =
T extends [infer X extends string, infer Y extends string, infer Z extends string]
? LongestCommonPrefixCore<Reverse<X>, Reverse<Y>> extends infer A extends string
? A extends ""
? ""
: LongestCommonPrefixCore<Reverse<A>, Reverse<Z>>
: ""
: never;

Trace(中級)

回答
type Trace<T extends any[][], L extends any[] = []> =
T['length'] extends L['length']
? never
: T[L['length']][L['length']] | Trace<T, [...L, 1]>;

IsAlphabet(中級)

回答
const alphabets = [...[...Array(26)].map((a, b) => (10 + b).toString(36)), ...[...Array(26)].map((a, b) => (10 + b).toString(36)).join('').toUpperCase()];
type Alphabets = [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z"
][number]
type ArrayUnionType<T extends string[]> = T[number];
type IsAlphabet<S extends string> = S extends Alphabets ? true : false;