例
こういう OneOf
が欲しい
type FetchData<T = {}, E = Error> = OneOf<{
data: T,
error: E,
loading: boolean
}>
var example: FetchData = {}; // Error
var example: FetchData = { data: {} }; // OK
var example: FetchData = { data: {}, error: undefined }; // OK
var example: FetchData = { data: {}, error: Error() }; // Error
実装
type Mask<T, K extends keyof T = keyof T> = Pick<T, K> &
{ [key in Exclude<keyof T, K>]?: undefined };
type OneOf<T, K extends keyof T = keyof T> = K extends keyof T
? Mask<T, K>
: never;
解説
書こうと思ったら、かなり近いものがすでにあった(TypeScriptで最低一つは必須なオプションオブジェクトの型を作る)ので割愛
おまけ
こういうのを定義して
type NoneOf<T> = Mask<T, never>;
type OneOrNoneOf<T> = OneOf<T> | NoneOf<T>;
こういうこともできる
type FetchResult<T = {}, E = Error> = OneOrNoneOf<{
data: T,
error: E
}>
type FetchState = OneOrNoneOf<{
loading: boolean,
loaded: boolean
}>
type FetchData<T = {}, E = Error> = FetchResult<T, E> & FetchState
var example: FetchData = { data: {}, error: undefined }; // OK
var example: FetchData = { data: {}, error: Error() }; // Error
var example: FetchData = { data: {}, error: undefined, loading: true }; // OK
var example: FetchData = { data: undefined, error: Error(), loading: true }; // OK
var example: FetchData = { data: {}, error: Error(), loading: true }; // Error