Убедите TypeScript в том, что у объекта не будут отсутствовать требуемые ключи - PullRequest
1 голос
/ 09 июля 2020

У меня следующая ситуация:

const user: UserObj = User.get(userId);

if ([user.foo, user.bar, user.baz].some((k) => !k))
  throw new Error(`Missing fields for user ${userId}`);

const createParams: CreateParams = {
  firstName: user.firstName,
  lastName: user.lastName,
  email: user.email,
  phone: user.phone,
  foo: user.foo,
  bar: user.bar,
  baz: user.baz
};

Поскольку foo bar baz требуются в CreateParams, TS жалуется, потому что эти ключи являются необязательными ключами в UserObj, однако я считаю, что застрахован от этого с помощью моего .some чека, но TS все еще жалуется. Как я могу убедить TS, что требуемые ключи будут там?

Ответы [ 2 ]

3 голосов
/ 09 июля 2020

Есть несколько способов сделать это. Один из способов - извлечь защиту в функцию:

interface HasOptional extends UserObj {
    foo: string,
    bar: string,
    baz: string,
}

function hasOptional(user: UserObj): user is HasOptional {
    return [user.foo, user.bar, user.baz].every(k => k);
}

if (!hasOptional(user))
    throw new Error('missing fields');

Другой способ - переписать условное выражение, чтобы TypeScript мог его понять:

if (!user.foo || !user.bar || !user.baz)
    throw new Error('missing fields');

В качестве небольшого примечания, это может быть удивительно использовать «истинность» для проверки существования свойств, потому что !"" истинно, !0 истинно и некоторые другие. Если вы используете .some(k => !k) для проверки отсутствующих свойств, это вызовет исключение для отсутствующих свойств и пустых строк, которые могут быть или не быть тем, что вы хотите. Обдумайте, подходит ли один из следующих тестов:

// Works if 0/''/false are legal values for foo/bar/baz.
function hasOptional(user: UserObj): user is HasOptional {
    return [user.foo, user.bar, user.baz].every(k != null);
}

// Also works if null is a legal value for foo/bar/baz.
function hasOptional(user: UserObj): user is HasOptional {
    return [user.foo, user.bar, user.baz].every(k !== undefined);
}

// Works even if undefined is a legal value for foo/bar/baz.
function hasOptional(user: UserObj): user is HasOptional {
    return ['foo', 'bar', 'baz'].every(k in user);
}
1 голос
/ 09 июля 2020

Если машинописный текст не доверяет вашему чеку, я думаю, другого выхода нет. Используйте @ts-ignore или ||.

//@ts-ignore
foo: user.foo
// or
bar: user.bar || ''

Если вам это не нравится, вы можете определить другой тип, чтобы сообщить ts, что проверка типов была выполнена.

Например:

// interface TypeChecked extends User
type TypeChecked {
   foo: string;
   bar: boolean;
   baz: any;
}

const createParams: CreateParams = {
  firstName: user.firstName,
  lastName: user.lastName,
  email: user.email,
  phone: user.phone,
  foo: (<TypeChecked> user).foo,
  bar: (<TypeChecked> user).bar,
  baz: (<TypeChecked> user).baz
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...