LoginSignup
3
0

More than 3 years have passed since last update.

TypeScriptで指定した内のちょうど1つのエントリーだけが存在するオブジェクト型を作る

Last updated at Posted at 2020-11-24

こういう 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

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0