Свойство интерфейса зависит от другого свойства - PullRequest
1 голос
/ 07 апреля 2020

Допустим, у меня есть следующий интерфейс:

interface TestInterface {
  id?: string;
  type?: string;
}

Можно ли переписать таким образом, чтобы при выполнении проверки id! == undefined автоматически значит что тип свойство тоже определено?

Ответы [ 3 ]

6 голосов
/ 07 апреля 2020

Вы можете mimi c с типами объединения.

Простой пример:

interface INonNullable {
    id: string;
    type: string;
}
interface INullable {
    id?: undefined;
    type?: undefined;
}
type FinalType = INonNullable | INullable;

function testId(x: FinalType) 
{
  if (x.id !== undefined) {
    x.type // string
  }
}

FinalType необязательно, вы можете просто использовать (x: INonNullable | INullable) везде.

Добавить функцию защиты типа:

Вы также можете создать функцию с защитой типа для проверки ваших критериев и сужения типа таким образом:

interface INonNullable {
    id: string;
    type: string;
}
interface INullable {
    id?: undefined;
    type?: undefined;
}
type FinalType = INonNullable | INullable;

function isNonNullable(x: FinalType): x is INonNullable
{
  return x.id !== undefined;
}

let x = {};

if (isNonNullable(x)) {
  x.type // string;
}

У вас есть больше информации об этом в документации Typescript: Определяемые пользователем охранники типов

Многоразовые Empty<T>:

Еще один изящный вариант, как упоминалось в комментарии Патрика Робертса, для создания более многократно используемого решения с использованием сопоставленных типов и обобщений:

interface INonNullable {
    id: string;
    type: string;
}
type Empty<T> = {
  [K in keyof T]?: undefined;
}
type FinalType<T> = T | Empty<T>;

function testId(x: FinalType<INonNullable>) {
  if (x.id !== undefined) {
    x.type // string
  }
}
1 голос
/ 07 апреля 2020

Вот способ сделать то, что вы хотите, используя union:

interface IdWithType {
  id: string;
  type: string;
}

interface WithoutId {
  id?: never;
  type?: string;
}

type TestInterface = IdWithType | WithoutId

// You cannot instansiate an object of type TestInterface with an id and with out a type

const yo: TestInterface = { // Type '{ id: string; }' is not assignable to type 'TestInterface'.
  id: "hey"
}


const testFunction = (a: TestInterface) => {
  if (a.id) {
    const b = a.type // string
  }
  const c = a.type // string | undefined
}
1 голос
/ 07 апреля 2020

Давайте рассмотрим ваш пример:

interface TestInterface {
  id?: string;
  type?: string;
}

const objectForTest: TestInterface = {
  id: '12345',
  type: 'some type'
}

Вы можете сделать это следующими способами:

1) objectForTest?.id

Если этот оператор соответствует undefined , он вернет это значение без выброса TypeError.

Это эквивалентно:

const testValue = (objectForTest === null || objectForTest === undefined) ?
    undefined 
    :
    objectForTest.id;

2) objectForTest!.id

В этом случае вы говорите Тип проверки: «Эй, я обещаю вам, что objectForTest это не null или undefined».

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