MappedTypes で Unpacked が可能に
従来 Tuple や Promise に利用できた ConditionalTypes による Unpacked が MappedTypes でも可能になりました。まずは公式に掲載されている Unpacked型 を見てみます。戻り型を抽出している件は謎ですが、要するに Unwrapper と解釈して問題ないでしょう。
type Unpacked<T> =
T extends (infer U)[] ? U :
T extends (...args: any[]) => infer U ? U :
T extends Promise<infer U> ? U :
T;
これが v3.1 から次の様に MappedTypes でも可能になりました。個人的にかなり大きい変更点だと思っていますが、公式ではまだアナウンスされていません。ChildNode の UnionTypes を得ることができます。これが、本題の件に影響を与えています。
type Unwrap<T> = T extends {[K in keyof T]: infer U} ? U : never
本題
タイトルで言及している「不要」とは、型定義のハードコーディングを指します。ObjectMap から UnionTypes を得ることができるので、ActionCreators ファイルから直接 Actions型を推論することができます。こんな感じの ActionCreators ファイルがあるとします。いたって普通ですが、ActionType は StringLiteralTypes でないとマズイので、Assertion をつけておきます。戻り型の Annotation は付与しません。
export function increment() {
return { type: 'INCREMENT' as 'INCREMENT' }
}
export function decrement() {
return { type: 'DECREMENT' as 'DECREMENT' }
}
export function setCount(amount: number) {
return { type: 'SET_COUNT' as 'SET_COUNT', payload: amount }
}
export function setName(value: string) {
return { type: 'SET_NAME' as 'SET_NAME', payload: value }
}
少し加工を加えないと期待する UnionTypes にはならないので、組み込み UtilityType の ReturnType
で戻り型の推論導出をしておきます。これに、上記の Unwrapper を併せると次の様になります。CreatorsToActions 型 と称して再利用できる様に書き出しておきます。
type Unwrap<T> = T extends {[K in keyof T]: infer U} ? U : never
type ReturnTypes<T> = {
[K in keyof T]: T[K] extends (...args: any[]) => any ?
ReturnType<T[K]> :
never
}
export type CreatorsToActions<T> = Unwrap<ReturnTypes<T>>
定常開発での利用例
import した ActionCreators ファイルを、CreatorsToActions型で変換します。あとは reducer の引数にキャストすればOK。下段は Actions型の内訳です。
import * as creators from './creators'
import { CreatorsToActions } from 'path/to/definition'
type Actions = CreatorsToActions<typeof creators>
function reducer(state: State, action: Actions) {
// ...
}
type Actions = {
type: 'INCREMENT';
} | {
type: 'DECREMENT';
} | {
type: 'SET_COUNT';
payload: number;
} | {
type: 'SET_NAME';
payload: string;
}
大袈裟なヘルパーモジュールを利用せずに、この定義が自動で推論出来る時代。幸せですね。
宣伝
この変更で可能になった様々な型変換について書いた同人誌を、技術書典5で頒布します。技術書典にお越しの方はお立ち寄り頂けると嬉しいです。サークルは 【か73】潜推艦 です。