type-challenges
型パズルの演習問題集
type-challenges/type-challenges
いうなれば型パズル100本ノックのようなものだろう
100本ノック
やり方
READMEの問題一覧から問題を選んでクリックする
問題が記述されたmarkdownに飛ぶ
そこにあるhttps://img.shields.io/badge/-Take%20the%20Challenge-3178c6?logo=typescript&logoColor=white#.pngを押すと、コードがあらかじめ入力されたTS Playgroundに飛ぶ
そこで直接編集して、Type ErrorsをなくせばOK
他の人の回答はhttps://img.shields.io/badge/-Check%20out%20Solutions-de5a77?logo=awesome-lists&logoColor=white#.pngから見れる
like順にsortされているので、良さげな解答例から順に見れる
issueにcursorをhoverすると便利
issueの冒頭にある解答が表示される
マウスを動かすだけで複数の解答をざっと見れる
/mrsekut-p/type-challenges
TypeScriptの"型"を学びたいあなたへ。type-challengesのすゝめ - Qiita
以下、ネタバレ注意
warm-up (1)
✅️13・Hello World
easy (13)
✅️4・Pick
Pick<T, K extends keyof T>
$ type Pick<T, K extends keyof T> = { Key in K: TKey };
✅️7・Readonly
Readonly<T>
$ type Readonly<T> = { readonly K in keyof T: TK };
✅️11・Tuple to Object
TupleToObject<T extends readonly (string | number | symbol)[]>
$ type TupleToObject<T extends readonly (string | number | symbol)[]> = { [K in Tnumber]: K };
✅️type error = TupleToObject<[[1, 2], {}]>をerrorにできなかった
2024-07-15 00:56:37 extendsで条件分岐するのではなく、Tに予め型制約をかけるとtype errorにできる
code:diff
- type TupleToObject<T extends readonly []> = Tnumber extends string | number | symbol ? { [K in Tnumber]: K }: never;
+ type TupleToObject<T extends readonly (string | number | symbol)[]> = { [K in Tnumber]: K };
✅️14・First of Array
First<T extends any[]>
$ type First<T extends unknown[]> = T extends [infer E, ...unknown[]] ? E : never;
extends unknown[]とextends any[]の違いはなさそうtakker.icon
一通り調べたが、言及がなかった
anyは本当に必要なときのみ登場させたいので、extends unknown[]を使うことにする
別解https://github.com/type-challenges/type-challenges/issues/16315
空配列をextendsする
$ type First<T extends unknown[]> = T extends [] ? never : T0
T["length"]を使う
$ type First<T extends uknown[]> = T"length" extends 0 ? never : T0
T["length"]は、
Tが配列型のときnumber
TがTypeScriptのTuple型のとき0 | 1 | 2 | ...
になる/mrsekut-p/IsTuple<T>#647c0b4919827000007dce3a
T[0] extendsa T[number]/mrsekut-p/TypeScriptのあるある部分型の型制約と条件分岐#61c83c311982700000150b5d
[][number]がneverになることを使っている
✅️18・Length of Tuple
Length<T extends readonly unknown[]>
$ type Length<T extends readonly unknown[]> = T"length";
T["length"]で楽に実装できる
別解
$ type Length<T extends readonly unknown[]> = T extends { length: infer N } ? N : never;
T[K]で済むところを回りくどく書いただけ
✅️43・Exclude
Exclude<U,E>
$ type Exclude<U, E> = U extends E ? never : U
なぜこれでunion (typescript)を分割できるかは後日調べるtakker.icon
union distributionあたりが関わっているっぽい
189・Awaited
Awaited<T>
Promise<T>をTにするやつ
Promise<Promise<T>>やPromiseLikeにも対応させる
Promise
$ type
✅️268・If
If<C, T, F>
$ type If<C extends boolean, T, F> = C extends true ? T : F;
C = booleanのときは、union distributionでT | Fになる
✅️533・Concat
Concat<T, U>
$ type Concat<T extends readonly unknown[], U extends readonly unknown[]> = ...T, ... U
extends readonly unknown[]でTypeScriptのTuple型にも対応している
898・Includes
code:898.ts
type Includes<T extends readonly any[], U> = T0 extends U ? U extends T0 ? true : Includes2<T, U> : Includes2<T, U>
type Includes2<T extends readonly any[], U> = T extends unknown ? false : Includes<Shift<T>, U>;
type Shift<T extends readonly any[]> = T extends unknown, ...(infer V) ? V: never;
これだと一部が失敗する
なぜextends readonly any[]?takker.icon
2024-07-15 00:30:38 /mrsekut-p/TypeScriptのあるある部分型の型制約と条件分岐#61cb2f7d1982700000c88fe8
extends unknown[]は配列型のみ、TypeScriptのTuple型不可
extends readonly unknown[]はTypeScriptのTuple型のみ、配列型不可
という違いらしい
✅️3057・Push
$ type Push<T extends any[], U> = ...T, U
✅️3060・Unshift
$ type Unshift<T extends any[], U> = U, ...T
3312・Parameters
Parameters<Fn>
medium (97)
2・Get Return Type
ReturnType<Fn>
3・Omit
Omit<T, K extends keyof T>
8・Readonly 2
9・Deep Readonly
$ type DeepReadonly<T> = T extends Record<string, unknown> ? { readonly K in keyof T: DeepReadonly<TK> } : T
これだと配列やmapが壊れるため、ReadonlyMap<T>などにfallbackする必要あり
DeepReadonly<T>
10・Tuple to Union
12・Chainable Options
15・Last of Array
16・Pop
20・Promise.all
62・Type Lookup
106・Trim Left
108・Trim
110・Capitalize
116・Replace
119・ReplaceAll
191・Append Argument
296・Permutation
298・Length of String
459・Flatten
527・Append to object
529・Absolute
531・String to Union
599・Merge
612・KebabCase
645・Diff
949・AnyOf
1042・IsNever
1097・IsUnion
1130・ReplaceKeys
1367・Remove Index Signature
1978・Percentage Parser
2070・Drop Char
2257・MinusOne
2595・PickByType
2688・StartsWith
2693・EndsWith
2757・PartialByKeys
2759・RequiredByKeys
2793・Mutable
2852・OmitByType
2946・ObjectEntries
3062・Shift
3188・Tuple to Nested Object
3192・Reverse
3196・Flip Arguments
3243・FlattenDepth
3326・BEM style string
3376・InorderTraversal
4179・Flip
4182・Fibonacci Sequence
4260・AllCombinations
4425・Greater Than
4471・Zip
4484・IsTuple
IsTuple<T>
4499・Chunk
4518・Fill
4803・Trim Right
5117・Without
5140・Trunc
5153・IndexOf
5310・Join
5317・LastIndexOf
5360・Unique
Unique<T>
配列の重複を除去するのTypeScriptのTuple型 ver.
$
無限ループになってしまったtakker.icon
急いでいるので答えを見る
やっぱりEqual<X, Y>は必須か
5821・MapTypes
7544・Construct Tuple
8640・Number Range
8767・Combination
8987・Subsequence
9142・CheckRepeatedChars
9286・FirstUniqueCharIndex
9616・Parse URL Params
9896・GetMiddleElement
9898・Appear only once
9989・Count Element Number To Object
10969・Integer
16259・ToPrimitive
17973・DeepMutable
18142・All
18220・Filter
21104・FindAll
21106・Combination key type
21220・Permutations of Tuple
25170・Replace First
25270・Transpose
26401・JSON Schema to TypeScript
これであっているはずなんだが、うまくいかないな……
code:26401.ts
type toType<Literal extends string> = Literal extends "string"
? string
: Literal extends "number"
? number
: Literal extends "boolean"
? boolean
: Literal extends "object"
? Record<string, unknown>
: Literal extends "array"
? unknown[]
: unknown;
type JSONSchema2TS<T> =
T extends { type: string }
? T extends { enum: infer U}
? U extends toType<T"type">[] ? Unumber : never
: T"type" extends "object"
? T extends { properties: infer O }
? O extends Record<string, unknown>
? T extends { required: infer R }
? R extends (keyof O)[]
? { [K in Rnumber]: JSONSchema2TS<OK> }
& { [K in Exclude<keyof O, Rnumber>]?: JSONSchema2TS<OK> }
: { K in keyof O?: JSONSchema2TS<OK> }
: { K in keyof O?: JSONSchema2TS<OK> }
: never
: toType<T"type">
: T"type" extends "array"
? T extends { items: infer O }
? O extends Record<string, unknown>
? JSONSchema2TS<O>[]
: never
: toType<T"type">
: toType<T"type">
: never;
27133・Square
27152・Triangular number
27862・CartesianProduct
27932・MergeAll
27958・CheckRepeatedTuple
28333・Public Type
29650・ExtractToObject
29785・Deep Omit
30301・IsOdd
30430・Tower of hanoi
30958・Pascal's triangle
30970・IsFixedStringLiteralType
hard (52)
6・Simple Vue
17・Currying 1
55・Union to Intersection
57・Get Required
59・Get Optional
89・Required Keys
90・Optional Keys
112・Capitalize Words
114・CamelCase
147・C-printf Parser
213・Vue Basic Props
223・IsAny
IsAny<T>
$ type IsAny<T> = 0 extends (1 & T) ? true : false;
any判定なんてできるんだtakker.icon
270・Typed Get
300・String to Number
399・Tuple Filter
472・Tuple to Enum Object
545・printf
553・Deep object to unique
651・Length of String 2
730・Union to Tuple
847・String Join
956・DeepPick
1290・Pinia
1383・Camelize
2059・Drop String
2822・Split
2828・ClassPublicKeys
2857・IsRequiredKey
2949・ObjectFromEntries
4037・IsPalindrome
5181・Mutable Keys
5423・Intersection
6141・Binary to Decimal
7258・Object Key Paths
8804・Two Sum
9155・ValidDate
9160・Assign
9384・Maximum
9775・Capitalize Nest Object Keys
13580・Replace Union
14080・FizzBuzz
14188・Run-length encoding
15260・Tree path array
19458・SnakeCase
25747・IsNegativeNumber
28143・OptionalUndefined
30178・Unique Items
30575・BitwiseXOR
31797・Sudoku
31824・Length of String 3
32427・Unbox
32532・Binary Addition
extreme (17)
5・Get Readonly Keys
151・Query String Parser
216・Slice
274・Integers Comparator
462・Currying 2
476・Sum
517・Multiply
697・Tag
734・Inclusive Range
741・Sort
869・DistributeUnions
925・Assert Array Index
6228・JSON Parser
7561・Subtract
31447・CountReversePairs
31997・Parameter Intersection
33345・Dynamic Route
#2024-10-07 13:48:00
#2024-09-04 11:20:41
#2024-07-14 18:25:06
#2024-06-10 12:18:02