Closed10
TypeScriptで型関数を書く練習をする
ピン留めされたアイテム
// 指定したキーの型を置き換える
type Replace<T, K extends keyof T, U> = Omit<T, K> & {
[k in K]: U
};
// 指定したキーのみをプロパティに持つオブジェクト型を作る
type Extract2<T, K extends keyof T> = {
[k in K]: T[k]
};
// 指定したキーの値をnullable型にする
type Nullable<T, K extends keyof T> = Omit<T, K> & {
[k in K]: T[k] | null
}
// 値が配列であるキーのみをプロパティに持つオブジェクト型を作る
type ArrayProps<T> = {
[
// k in J (値が配列であるようなキーの集まり)
k in {
// 値が配列であるようなキーを選択する
[j in keyof T]: T[j] extends Array<infer _>
? j
: never
}[keyof T]
]: T[k]
}
// 指定したキーのみをプロパティに持つオブジェクト型を作る
// ただし、値が配列であるようなプロパティしか指定できない
type ExtractArrayElem<T, K extends keyof ArrayProps<T>> = {
[k in K]: T[k]
}
// 指定した配列型の要素の型を得る
type ArrayElem<T> = T extends Array<infer U> ? U : never;
// これでもOK
type ArrayElem2<T> = T extends (infer U)[] ? U : never;
Conditional types に一般型を入れて、その型にユニオン型を入れると、Conditional typesは分配的な挙動をする。
この挙動を防ぐには、extends
の両側を[]
で囲む。
type A<T> = T extends any ? T[] : never;
// A<string | number> => string[] | number[]
type B<T> = [T] extends [any] ? T[] : never;
// B<string | number> => (string | number)[]
なんかの役に立たないかと思ってC++のenable_if
っぽいものを書いたけど、TypeScriptではうまく生かせない
C++では条件に当てはまらずにテンプレートのSubstitutionに失敗した時に次の候補を見ることでコンパイルエラーを回避できるというのがSFINAEだったけど、TypeScriptではnever型がそもそも合法な型だし、コンセプトから崩れてる
どうにかして、うまく関数の型パラメータ部分に条件を書けないものか
// B に渡された型が true であれば T が有効化され、そうでなければ Err が選択される型
type EnableIf<B, T = void, Err = never> = B extends true ? T : Err;
// T <: U は, T が U のサブタイプであるという意味
// never型は ⊥型; ∀t, never <: t
type OrNever<T> = T | never; // T | never == T
type AndNever<T> = T & never; // never
// unknown は ⊤型; ∀t, t <: unknown
type OrUnknown<T> = T | unknown; // => unknown
type AndUnknown<T> = T & unknown; // => T
このスクラップは2024/03/30にクローズされました