Closed15
💻 Type challenge / Medium (3 of 10) やっていくスレ
引越し元:
ReplaceAll
Replace の再帰版だとおもったが、微妙に違うっぽい
type ReplaceAll<S extends string, From extends string, To extends string> =
From extends ''
? S
: S extends `${infer L}${From}${infer R}`
? ReplaceAll<`${L}${To}${R}`, From, To>
: S
以下のテストが通らない
Expect<Equal<ReplaceAll<'foobarfoobar', 'ob', 'b'>, 'fobarfobar'>>,
Expect<Equal<ReplaceAll<'foboorfoboar', 'bo', 'b'>, 'foborfobar'>>,
Append Argument
type AppendArgument<Fn, A> = Fn extends (...args: infer Args) => infer Ret
? (...args: [...Args, A]) => Ret
: never
関数の引数を infer する方法がいつも曖昧
...args: infer T
の形 identifier: type
の形の発展で identifier が複数あると ...identifiers
みたいに rest operator (?) のようにまとめて取れる
とおぼえておぼえておこう
逆に tuple から関数の型を組み立てるときは
([...Args, A]) => Ret
ではダメで
(...args: [...Args, A]) => Ret
ここでも ...args:
が必要で、無いと A rest element must be last in a destructuring pattern.
みたいな、よくわからないことを言われてしまう
Permutation
Union を Tuple に変換するのどうするんだっけ?
Mapped Type 使えばいけそうな気がするが...
Length of String
tuple の length が型レベルで取得できることを利用する
type LengthOfString<S extends string, T extends string[] = []> =
S extends `${infer First}${infer Rest}`
? LengthOfString<Rest, [...T, First]>
: T['length']
-
S extends '${infer First}${infer Rest}'
で 文字列から先頭の1文字 (First) と残りの文字列(Rest) を取り出す -
? LengthOfString<Rest, [...T, First]>
で、再帰的 LengthOfString を適用して、対象の文字列(S)として Rest をわたす - 型変数 T は tuple 化した文字列を格納するための変数として利用する
-
S extends '${infer First}${infer Rest}'
の条件に合致しないという状況は、文字列の最後まで到達した場合なので、T['length']
で tuple の長さ ( = 文字列の長さ) を適用する
Flatten
tuple を [infer First, ...infer Rest]
で分解して再帰する方法をでできたけど、もうちょっと整理できそう
type Flatten<T extends [...any]> =
T extends [infer First, ...infer Rest]
? First extends any[]
? [...Flatten<First>, ...Flatten<[...Rest]>]
: [First, ...Flatten<[...Rest]>]
: T
少し整理した
type Flatten<T extends [...any]> =
T extends [infer First, ...infer Rest]
? [
...(First extends [...any] ? Flatten<First>: [First]),
...Flatten<Rest>
]
: T
-
[...any]
はany[]
でもよさそう - 最後の
: T
は、: []
でも結果的には同じになるっぽい
Append to object
type AppendToObject<T, U extends string, V> = {
[k in keyof T | U]: k extends keyof T ? T[k] : V
}
一応解けた
-
keyof T | U
でオブジェクトの key (k) にセットするものをT
の key とU
とする - 値の型については
k
にセットされている型を検査して-
T
の key に該当するものであればT[k]
でそのプロパティの型とする - そうでない場合は key は
U
のはずなのでV
を使用する
-
最初、以下と等価だと思ったけど違うのかな... ?
type AppendToObject<T, U extends string, V> = T & { [k in U]: V }
Absolute
文字列に変換する部分を ToS<T>
として切り出して考えてみた
type ToStr<T extends number | string | bigint> = `${T}`
type Absolute<T extends number | string | bigint> =
ToStr<T> extends `-${infer Num}`
? Num
: ToStr<T>
さほど複雑じゃないのでインライン化してもよさそう
type Absolute<T extends number | string | bigint> =
`${T}` extends `-${infer Num}`
? Num
: `${T}`
ここまでの進捗
Permutation がまだ理解できていないが、一旦次のスレへ
このスクラップは2023/12/09にクローズされました