TypeScriptのあるある部分型の型制約と条件分岐
TypeScriptで型定義する際の extends
周りのあるあるを集めておく
型定義の =
の
引数に取る型の制約を設ける
であることに注意する
両方とも、部分型で同じ話をしているので同じページに書いている

これを使いこなすためには、型の階層を把握していないといけないので難易度高いと思う

T extends object
record, array, functionを含むことに注意

配列である
TS extends unknown[]
tupleは許容しない
TS extends readonly unknown[]
ただの配列は許容しない
関数である
T extends (...args: unknown[]) => unkwnon>
T extends Fucntion
後者のほうが簡潔なので後者で書いている

T extends { [K in string]: unknown }
T extends Record<string, unknown>
これは、 {2: boolean, [symbol]: boolean}
のように、keyがnumberやsymbolのものも許容するので、直観通り「record」の条件として使える
なんで、numberやsymbolも行けるのかわからん
#??ちなみに、 [K in string]
を [K in number]
に変えても同じになる
T[] extends never[]
[T] extends [never]
K extends ${any}
常にtrueを返す
T extends unknown
T exrends any
引数の配列の要素数が1個以上かどうか
いっぱい書き方がある

T extends [unknown, ...unknown[]]
例.tstype Head<T extends unknown[]> =
T extends [unknown, ...unknown[]] ? T[0] : never;
T[0] extends T[number]
例.tstype Head<T extends unknown[]> =
T[0] extends T[number] ? T[0] : never
T extends [infer H, ...any[]]
例.tstype Head<T extends unknown[]> =
T extends [infer E, ...any[]] ? E : never;
T extends []
tstype Head<T extends unknown[]> =
T extends [] ? never : T[0];
T['length'] extends 0
tstype Head<T extends unknown[]> =
T['length'] extends 0 ? never : T[0];
共通で持っているpropertyの値を見て絞り込む
tstype Ts = { kind: 'ts'; hasTypeClass: false };
type Hs = { kind: 'hs'; hasTypeClass: true };
type Purs = { kind: 'purs'; hasTypeClass: true };
type Langs = Ts | Hs | Purs;
type HasTypeClass<Lang> =
Lang extends { hasTypeClass: true } ? Lang : never;
type HasTypeClassLangs = HasTypeClass<Langs>; // Hs | Purs