машинопись - как расширить интерфейс в определенном месте (расширить базовое состояние для библиотеки xstate) - PullRequest
0 голосов
/ 30 июня 2019

Я хочу иметь возможность расширять базовый интерфейс в одном или нескольких определенных местах.Идея состоит в том, чтобы иметь возможность определить базовое состояние для библиотеки xstate, которое может быть расширено для более конкретных целей.

У меня есть

interface Base {
   id:string;
   states:{
       init:{},
       loading:{},
       idle:{
            states:{
                  someBaseState:{}
            }

       }
   }
}

Я хочу знать, возможно ли с помощью машинописи расширить базовый интерфейс в определенном месте.например, свойство "idle"

interface Page "extends Base Idle Property" {
   id:string;
   states:{
       someOtherState:{}
   }
}

, так что результат равен

{
   id:string;
   states:{
       init:{},
       loading:{},
       idle:{
            id:string;
            states:{
                someBaseState:{}
                someOtherState:{}
            }
       }
   }
}

Я знаю, что могу определить Generic в Typescript следующим образом

interface Base<T> {
  id: string;
  states: {
    idle: T
  }
}

НоЯ хочу иметь возможность определять конкретные базовые свойства для состояния "простоя" (например) и не реализовывать его каждый раз полностью.

1 Ответ

0 голосов
/ 30 июня 2019

С учетом этих определений:

interface Base {
  id: string;
  states: {
    init: {};
    loading: {};
    idle: {
      states: {
        someBaseState: {};
      };
    };
  };
}

interface Page {
  id: string;
  states: {
    someOtherState: {};
  };
}

Самое простое, что можно сделать, это использовать пересечение вместо наследования, например:

type MyNewType = Base & { states: { idle: Page } };
interface MyNewInterface extends MyNewType {} // if you want in interface

Вы можете видеть, что он соответствует желаемой форме:

function foo(mni: MyNewInterface) {
    mni.states.init; // okay
    mni.states.idle.id; // okay
    mni.states.idle.states.someBaseState; // okay
    mni.states.idle.states.someOtherState; // okay
}

Этот тип может быть немного трудным для понимания как пересечение ... если вы действительно хотите, вы можете использовать вложенный сопоставленный тип , например:

type NestedId<T> = T extends object ? { [K in keyof T]: NestedId<T[K]> } : T;
type NestedExtend<T, U> = NestedId<T & U>;

type MyNewType2 = NestedExtend<Base, { states: { idle: Page } }>;

, который показывает следующий тип при проверке через IntelliSense:

// IntelliSense shows you
type MyNewType2 = {
    id: string;
    states: {
        init: {};
        loading: {};
        idle: {
            states: {
                someBaseState: {};
                someOtherState: {};
            };
            id: string;
        };
    };
}

В любом случае должно работать. Надеюсь, это поможет; удачи!

Ссылка на код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...