type-challenges の中級の易し目な問題に挑戦する【68問中52問】

## type challenge はこちら

https://github.com/type-challenges/type-challenges

## 初級編と基本的なテクニックはこちら

https://qiita.com/ItsukiN32/items/636ffa7299928aed59f1


## 初級との違い(個人の感想です)

- 再起処理が必要なケースがある

- カウントを取るテクニックを利用する

``` こんな感じ.ts
// 再帰処理をする場合に Hoge<T, [...Counter, 0]> とすることで、再帰処理した回数をカウントできる
Hoge<T, Counter extends 0[] = []> = ...
```

- いくつかは初級と大差ない問題がある 

## 以下解答

``` 2 - Get Return Type.ts
// (...arg: unknown[])とすると 戻り値がユニオン型の関数の戻り値が取れない
type MyReturnType<T extends Function> = T extends (...arg: any[]) => infer R ? R : never
```

``` 3 - Omit.ts
type MyOmit<T, K extends keyof T> = {
  [P in keyof T as P extends K ? never : P]: T[P]
}
```

``` 8 - Readonly 2.ts
// K がない場合の挙動が K = keyof T である点に注意
type MyReadonly2<T, K extends keyof T = keyof T> = {
  readonly [P in K]: T[P]
} & {
  [P in keyof T as P extends K ? never: P]: T[P]
}
```

``` 9 - Deep Readonly.ts
type NonNestedObject = string | number | boolean | Function
type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends NonNestedObject ? T[P] : DeepReadonly<T[P]>
}
```

``` 10 - Tuple to Union.ts
type TupleToUnion<T extends unknown[]> = T[number]
```


``` 15 - Last of Array.ts
type Last<T extends any[]> = T extends [...infer L, infer R] ? R : never
```

``` 16 - Pop.ts
type Pop<T extends any[]>  = T extends [...infer L, infer R] ? L : never
```

``` 20 - Promise.all.ts
declare function PromiseAll<T extends any[]>(values: readonly [...T]): 
//には以下の両方入るが、
declare function PromiseAll<T extends any[]>(values: [...T]): 
//には as const がついていない方がしか入らない。
PromiseAll([1, 2, Promise.resolve(3)] as const)
PromiseAll([1, 2, Promise.resolve(3)])

// T = [1,2,3] に対し、
// { [key in keyof T] : T[key] } とすると、プロパティは必ず0,1,2が入り、 T[key]の配列型になる

// 答え
declare function PromiseAll<T extends any[]>(values: readonly [...T]): 
  Promise<{
    [key in keyof T] : T[key] extends Promise<any> ? Awaited<T[key]> : T[key] 
  }>
```

``` 62 - Type Lookup.ts
type HasType = { type: string }
type LookUp<U extends HasType, T extends string> = U extends { type: T } ? U : never
```

``` 106 - Trim Left.ts
type TrimTarget = ' ' | "\n" | "\t"
type TrimLeft<S extends string> = S extends `${TrimTarget}${infer A}`
  ? TrimLeft<A>
  : S
```

``` 108 - Trim.ts
type TrimTarget = ' ' | "\n" | "\t"
type Trim<S extends string> = S extends `${TrimTarget}${infer A}` | `${infer A}${TrimTarget}`
  ? Trim<A>
  : S
```

``` 110 - Capitalize.ts
type MyCapitalize<S extends string> = S extends `${infer A}${infer Rest}`
  ? `${Uppercase<A>}${Rest}`
  : S
```

``` 116 - Replace.ts
type Replace<S extends string, From extends string, To extends string> = S extends `${infer L}${From}${infer R}`
  ? From extends ''
    ? S
    : `${L}${To}${R}`
  : S
```

``` 119 - ReplaceAll.ts
type ReplaceAll<S extends string, From extends string, To extends string> = S extends `${infer L}${From}${infer R}`
  ? From extends ''
    ? S
    : `${L}${To}${ReplaceAll<R , From, To>}`
  : S
```

``` 191 - Append Argument.ts
type AppendArgument<Fn, A> = Fn extends (...args: infer Args) => infer R
  ? (...args: [...Args, A]) => R
  : never
```


``` 298 - Length of String.ts
// S が '' になるまで再帰処理をする
// すると Temp は S の文字列の数と同じだけの要素をもつ配列になる
type LengthOfString<S extends string, Temp extends string[] = []> = S extends `${infer L}${infer R}`
  ? LengthOfString<R, [...Temp, L]>
  : Temp['length']
```

``` 459 - Flatten.ts
type Flatten<T extends unknown[]> = T extends [infer L, ...infer R]
  ? L extends unknown[]
    ? Flatten<[...L, ...R]>
    : [L, ...Flatten<R>]
  : T
```

``` 527 - Append to object.ts
type AppendToObject<T, U extends PropertyKey, V> = {
  [P in keyof T|U]: P extends keyof T ? T[P] : V
}
```

``` 529 - Absolute.ts
// 一旦文字列に変換することで `-${infer A}` でstringもnumberも同じように扱うことができるようになる
type Absolute<T extends number | string | bigint> = `${T}` extends `-${infer A}`
  ? `${A}`
  : `${T}`
```

``` 531 - String to Union.ts
type StrToArray<S extends string, A extends unknown[] = []> = S extends `${infer L}${infer R}`
  ? [L, ...StrToArray<R, [L]>]
  : []
type StringToUnion<T extends string> = StrToArray<T>[number]
```


``` 599 - Merge.ts
type Merge<F, S> = {
  [P in keyof F| keyof S]: P extends keyof S 
    ? S[P]
    : P extends keyof F
      ? F[P]
      : never
}
```

``` 612 - KebabCase.ts
type UpperCaseAlphabet = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' // 他にも追加する
type KebabCase<S extends string> = S extends `${infer L}${infer R}`
  ? L extends UpperCaseAlphabet 
    ? KebabCase<`${Lowercase<L>}${R}`> // 最初が大文字である場合のみの対応
    : R extends `${infer RL}${infer RR}`
      ? RL extends UpperCaseAlphabet 
        ? `${L}-${KebabCase<`${Lowercase<RL>}${RR}`>}` // 二文字目が大文字である場合
        : `${L}${KebabCase<R>}`
      : S
  : S /
```

``` 645 - Diff.ts
// もっとスマートなやり方あるかも
type Diff<O, O1> = {
  [P in keyof O| keyof O1 as P extends keyof O & keyof O1 ? never : P]: P extends keyof O
    ? O[P]
    : P extends keyof O1
      ? O1[P]
      : never
}
```

``` 949 - AnyOf.ts
// {} を表現するには Record<string, never> を使う
type Falsy = 0 | '' | false | [] | Record<string, never>
type AnyOf<T extends readonly any[]> = T extends Falsy[] ? false : true
```

``` 1042 - IsNever.ts
type IsNever<T> = [T] extends [never] ? true : false

// 以下の場合、 右辺の extends の評価対象の T に never が入った瞬間、 never を返してしまう 
// [] に入れてやり、ワンクッション置くことで評価ができるようになる。
type IsNever<T> = T extends never ? true : false
type a = IsNever<never> //=> never
```



``` 1130 - ReplaceKeys.ts
type ReplaceKeys<U, T, Y> = {
  [P in keyof U]: P extends T 
    ? P extends keyof Y
      ? Y[P] 
      : never
    : U[P]
}
```

``` 1367 - Remove Index Signature.ts
type RemoveIndexSignature<T> = {
  [K in keyof T as string extends K 
    ? never 
    : number extends K 
      ? never 
      : symbol extends K 
        ? never : K
  ]: T[K]
}
```

``` 1978 - Percentage Parser.ts
type PlusOrMinus = '+' | '-'
type PercentageParser<A extends string> = A extends `${infer L extends PlusOrMinus}${infer R}`
  ? R extends `${infer C}%`
    ? [L, C, '%']
    : [L, R, '' ]
  : A extends `${infer L}%`
    ? ['', L, '%' ]
    : ['', A, '']
```

``` 2070 - Drop Char.ts
// 以下をクリアせずに回答している人が多いイメージでした
// Expect<Equal<DropChar<'butter fly!', ''>, 'butterfly!'>>,

type DropChar<S, C> = C extends ''
  ? DropChar<S, ' '>
  : S extends `${infer L}${infer R}`
    ? L extends C
      ? DropChar<R, C>
      : `${L}${DropChar<R, C>}`
    : S
```    


``` 2595 - PickByType.ts
type PickByType<T, U> = {
  [P in keyof T as T[P] extends U ? P : never ]: T[P]
}
```

``` 2688 - StartsWith.ts
type StartsWith<T extends string, U extends string> = T extends `${U}${infer R}` ? true : false
```

``` 2693 - EndsWith.ts
type EndsWith<T extends string, U extends string> = T extends `${infer R}${U}` ? true : false
```


``` 2759 - RequiredByKeys.ts

// ↓この記法を知っているかどうかが肝
// [P in T]-?: T[P] 
type Merge<T> = {
  [P in keyof T]: T[P]
}

type RequiredByKeys<T, K = any> = Merge<{
  [P in keyof T as P extends K ? P : never]-?: T[P]
} & {
  [P in keyof T as P extends K ? never : P]?: T[P]
}>
```

``` 2793 - Mutable.ts
type Mutable<T extends object> = {
  -readonly [P in keyof T]: T[P] // この記法を知っているかが肝
}
```

``` 2852 - OmitByType.ts
type OmitByType<T, U> = {
  [P in keyof T as T[P] extends U ? never : P]: T[P]
}
```


``` 3062 - Shift.ts
type Shift<T extends unknown[]> = T extends [infer L, ...infer R] ? R : []
```



``` 3192 - Reverse.ts
type Reverse<T extends unknown[]> = T extends [infer L, ...infer R]
  ? [...Reverse<R>, L]
  : []
```

``` 3196 - Flip Arguments.ts
type Reverse<T extends unknown[]> = T extends [infer L, ...infer R]
  ? [...Reverse<R>, L]
  : []
type FlipArguments<T extends (...args: any) => any > = T extends (...args: infer A) => infer B
  ? (...args: Reverse<A>) => B
  : never
```



``` 3326 - BEM style string.ts
type BEM<B extends string, E extends string[], M extends string[]> = E extends []
  ? M extends []
    ? B
    : `${B}--${M[number]}`
  : M extends []
    ? `${B}__${E[number]}`
    : `${B}__${E[number]}--${M[number]}`
```



``` 4179 - Flip.ts
// Type 'T[P]' is not assignable to type 'string | number | bigint | boolean | null | undefined'.
// と出たので、そのままそれを使った
type Stringifiable = string | number | bigint | boolean | null | undefined
type Flip<T extends object> = {
  [P in keyof T as T[P] extends Stringifiable ? `${T[P]}` : never]: P 
}
```


``` 4425 - Greater Than.ts
type GreaterThan<T extends number, U extends number, A extends 0[] = []> = U extends A['length']
  ? T extends A['length']
    ? false
    : true
  : T extends A['length']
    ? false
    : GreaterThan<T, U, [...A, 0]>
```


``` 4484 - IsTuple.ts 
type IsTuple<T> = [T] extends [never] 
  ? false
  : T extends readonly [any?]
    ? true
    : false
```

``` 4499 - Chunk.ts
// まず 結果全体の配列と、 N個の要素でまとまった配列を作ることを考えた
type Chunk<T extends unknown[], N extends number, Memory extends unknown[] = [], Short extends unknown[] = []> = T extends [infer L, ...infer R]
  ? [0, ...Short]['length'] extends N // Short['length'] extends N だと想定より一回多くループが走るので 0 を足して強引にサイズを合わせた
    ? Chunk<R, N, [...Memory, [...Short, L]], []>
    : Chunk<R, N, Memory, [...Short, L]>
  : Short['length'] extends 0
    ? Memory
    : [...Memory, Short]
```

``` 4518 - Fill.ts
// すごい力技...笑
type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
  Count extends 0[] = [],
  Flag extends boolean = false
> = T extends [infer L, ...infer R]
  ? Start extends End
    ? T
    : Count['length'] extends Start
      ? [N, ...Fill<R,N,Start,End,[...Count, 0], true>]
      : Count['length'] extends End
        ? [L, ...Fill<R,N,Start,End,[...Count, 0], false>]
        : Flag extends true
          ? [N, ...Fill<R,N,Start,End,[...Count, 0], Flag>]
          : [L, ...Fill<R,N,Start,End,[...Count, 0], Flag>]
  : []
```

``` 4803 - Trim Right.ts
type TrimTarget = ' ' | "\n" | "\t"
type TrimRight<S extends string> = S extends `${infer A}${TrimTarget}`
  ? TrimRight<A>
  : S
```

``` 5117 - Without.ts
type Without<T, U extends number[]|number> = T extends [infer L, ...infer R]
  ? U extends number[]
    ? L extends U[number]
      ? [...Without<R, U>]
      : [L, ...Without<R, U>]
    : L extends U
      ? [...Without<R, U>]
      : [L, ...Without<R, U>]
  : []
```


``` 5140 - Trunc.ts
type Trunc<T extends string | number> = `${T}` extends `${infer L}.${infer R}` 
  ? L 
  : `${T}`
```

``` 5153 - IndexOf.ts
type IndexOf<T, U, Count extends 0[] = []> = T extends [infer L, ...infer R]
  ? Equal<L, U> extends true
    ? Count['length']
    : IndexOf<R, U, [...Count, 0]>
  : -1
```

``` 5310 - Join.ts
// ...infer R extends string[] としないと、 Rにstring以外の可能性が残るので、 Join<R, U> にR をアサインできない
type Join<T extends string[], U extends string | number> = T extends [infer L, ...infer R extends string[]]
  ? L extends string
    ? R extends []
      ? L
      : `${L}${U}${Join<R, U>}`
    : ''
  : never
```

``` 5317 - LastIndexOf.ts
type LastIndexOf<T, U, Count extends 0[] = [], Answer extends number = -1> =  T extends [infer L, ...infer R]
  ? Equal<L, U> extends true
    ? LastIndexOf<R, U, [...Count, 0], Count['length']>
    : LastIndexOf<R, U, [...Count, 0], Answer>
  : Answer
```

``` 5360 - Unique.ts
type Contain<T extends unknown[], S extends unknown> = T extends [infer L, ...infer R]
  ? Equal<L, S> extends true
    ? true
    : Contain<R, S>
  : false

type Unique<T extends unknown[], Answer extends unknown[] = []> = T extends [infer L, ...infer R] 
  ? Contain<Answer, L> extends true
    ? Unique<R, Answer>
    : Unique<R, [...Answer, L]>
  : Answer
```


``` 7544 - Construct Tuple.ts
type ConstructTuple<L extends number, M extends unknown[] = []> = M['length'] extends L
  ? M
  : ConstructTuple<L, [...M, unknown]>
```