Как написать охрану типа с включенным no-unsafe-any? - PullRequest
0 голосов
/ 10 февраля 2019

Я пытаюсь ужесточить свой код TS, используя более строгий набор правил lint, но я борюсь с тем, что должно быть законным использованием динамизма.

Я делаю защиту типа, чтобы обнаружить, есличто-то является итеративным (чтобы обернуть это в массив, если нет), и я понятия не имею, что сказать TS, кроме подавления правила lint, указывающего, что это кошерное:

function isIterable(obj: any): obj is Iterable<unknown> {
    return obj && typeof obj[Symbol.iterator] === 'function';
}

Я попытался изменить это на:

function isIterable(obj: undefined | {[Symbol.iterator]?: unknown}): obj is Iterable<unknown> {
    return !!obj && typeof obj[Symbol.iterator] === 'function';
}

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

Есть ли "чистый" способ сказать "да, я действительно хочу полагаться на JS, возвращающий undefined для доступа к свойству, которое не существует в объекте "?Особеннотак как в этом весь смысл написания охранников типа.

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Другая хорошая стратегия - использовать Partial с as приведением.

interface RegularForm {
    regular: number;
}

interface FancyForm extends RegularForm {
    fancy: string;
}

const isFancyForm = (instance: RegularForm): instance is FancyForm =>
    (instance as Partial<FancyForm>).fancy !== undefined;
0 голосов
/ 10 февраля 2019

Я не знаю, покупает ли что-то вроде no-unsafe-any слишком много внутри реализации защиты определенного пользователем типа , поскольку обычно весь смысл такогозащита типа должна позволить компилятору сузить значения, которые он обычно не может сделать с помощью встроенного сужения потока управления.Я бы, конечно, понял, приостановив правило линтера внутри такой реализации.

Но я думаю, что вы можете получить почти то поведение, которое вы ищете, вот так:

function isIterable(obj: unknown): obj is Iterable<unknown> {
  if ((typeof obj !== 'object') || (obj === null)) return false; 
  // obj is now type object
  const wObj: { [Symbol.iterator]?: unknown } = obj; // safely widen to wObj
  return typeof wObj[Symbol.iterator] === 'function'; 
}

Это несколько обручейчтобы прыгнуть, но идея состоит в том, чтобы использовать сужение потока управления для сужения unknown до object, а затем расширить object специально для типа с необязательным свойством, которое вы пытаетесь проверить (это происходит путем введения новой переменной).И, наконец, проверьте тип этого свойства в расширенном типе.Поскольку ключ свойства, который вы проверяете, является символьным типом, вам нужно упомянуть конкретное имя свойства в расширенном типе.Если ключ свойства является строкой, вы можете использовать подпись индекса строки :

function isPromise(obj: unknown): obj is Promise<unknown> {
  if ((typeof obj !== 'object') || (obj === null)) return false;
  // obj is now type object
  const wObj: {[k: string]: unknown} = obj; // safely widen to wObj
  return typeof wObj.then === 'function';
}

В любом случае, я надеюсь, что это приблизит вас к вашей цели.Удачи!

...