Машинопись: введите ровно одно свойство другого типа - PullRequest
1 голос
/ 28 мая 2020

У меня есть интерфейс, и я хочу создать тип, используя ключ этого интерфейса.

  • ключ может быть необязательным
  • ключ должен быть в этом интерфейсе

Пример

interface Test {
  a: string;
  b: string;
  c: string;
  d: string | undefined;
  e: string | undefined;
}

Мой новый тип может иметь одно свойство среди указанных выше ключей. Я написал, как показано ниже

type MyNewType<T> = {
  [key in keyof T]: T[key];
};

Я использовал этот тип как MyNewType<Test>, но обнаружил ошибку.

Тип '{a: string; } 'отсутствуют следующие свойства типа MyNewType: b, c, d, e.

Как я могу использовать свойство по желанию?

Уточнение

Я использую редуктор в React и вызываю функцию dispatch, которая принимает средство создания действий в качестве параметра. Test type - это тип состояния, а MyNewType<Test> - тип полезной нагрузки. Создатель действия принимает полезную нагрузку, и полезная нагрузка может быть { a: 'a'}, { b: 'b' } или { d: undefined }. Однако ошибка говорит о том, что полезная нагрузка должна содержать все свойства.

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Если вам не нужно решение generi c, вы можете использовать следующее:

MyNewType = { a: string }
          | { b: string }
          | { c: string }
          | { d: string | undefined }
          | { d: string | undefined };

Я не могу придумать, как сделать это для generi c type T .

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

{
  key: "a",
  value: "a"
}

Это может должно выполняться обычным c способом:

type MyNewType<T> = {
  key: keyof T;
  value: T[keyof T];
}

Однако это не очень точно, так как вы можете комбинировать любой ключ с любым значением.

Другой подход был бы :

type MyNewType<T, K extends keyof T> = {
  key: K;
  value: T[K];
}

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

function dispatch<K extends keyof Test>(testPayload: MyNewType<Test, K>) {
  // do something with payload
}

dispatch({ key: "a", value: "a" });        // OK
dispatch({ key: "a", value: undefined });  // Error, because Test.a cannot be undefined
dispatch({ key: "d", value: undefined });  // OK
dispatch({ key: "x", value: undefined });  // Error, because Test does not have property "x"

Edit

Я также пробовал следующее, чтобы создать тип точно так, как просили:

type MyNewType<T, K extends keyof T> = {
  [key: K]: T[K];
}

Но TypeScript выдает следующую ошибку на key:

Тип параметра подписи индекса должен быть либо 'string', либо 'number'.

1 голос
/ 28 мая 2020

Добавьте ? после ключей, которые являются необязательными

Например, если вы хотите сделать a & b необязательным

interface Test {
  a?: string;
  b?: string;
  c: string;
  d: string | undefined;
  e: string | undefined;
}

Ссылка: https://www.typescriptlang.org/docs/handbook/interfaces.html#optional -properties

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