Как получить интерфейс из свойств класса (без учета методов) в Typescript? - PullRequest
1 голос
/ 23 апреля 2020

У меня есть некоторый класс со всеми publi c членами (по существу, структура), и я хотел бы сохранить его данные:

class SomeClass {
  public foo: string;
  public bar: string;

  public getFooBar() { 
    return this.foo + this.bar;
  }
}

Как часть поиска хранилища, я хотел бы иметь интерфейс, который правильно определяет его, например:

interface ISomeClassData {
  foo: string;
  bar: string;
  // notice there is no getFooBar()
}

const test: ISomeClassData = magic();
if ("getFooBar" in test === false) {
  return "Success.  This is an interface, and not a class";
}

Один типичный (но неприменимый) способ сделать такую ​​вещь будет выглядеть так:

interface ISomeClassData {
  foo: string;
  bar: string;
}

class SomeClass extends ISomeClassData {
  // code omitted
}

В моем сценарии сумма свойств publi c в классе очень велико, и было бы очень легко добавить что-то в класс без добавления в интерфейс. Вместо этого я хотел бы получить интерфейс из класса.

Можно ли получить интерфейс из свойств класса (не используя методы) в Typescript?


Воображаемый пример:

type ISomeClassData = JustThePublicProperties<SomeClass>

1 Ответ

3 голосов
/ 23 апреля 2020

Звучит так, будто вам нужны все клавиши, которые не являются функциями, и вы хотите построить объект только из этих клавиш.

// Get the keys that are not functions. We consider these data.
type ClassDataKeys<T> = {

  // Iterate over each property.
  [K in keyof T]:

    // If the property is a function...
    T[K] extends (...args: any[]) => any

    // Functions are not allowed, use never to exclude it.
    ? never

    // Not a function, it is data, set the value of this property to its own key.
    : K

// Get the union of all values (which are now the keys that have not been set to `never`)
}[keyof T]

// Pick just the keys from the class that are ClassDataKeys.
type ClassData<T> = Pick<T, ClassDataKeys<T>>

// Works!
const test1: ClassData<SomeClass> = {
  foo: 'asd',
  bar: 'asd',
}

Детская площадка

Это двухступенчатый процесс. Сначала нужно использовать сопоставленный тип и условное выражение, чтобы проверить, является ли каждое свойство функцией. Затем соберите те имена свойств, которые не являются функциями. Наконец, выберите только имена свойств, которые считаются данными из класса.

...