Что такое правильная аннотация типа jsdo c для идентификатора try..catch? - PullRequest
0 голосов
/ 11 февраля 2020

При аннотировании JavaScript источников комментариями JSDo c, как вы аннотируете тип идентификатора try..catch?

try {
  throw new Error();
} catch (whatIsMyType) {
  console.error(whatIsMyType.message);
}

Я специально спрашиваю для TypeScript JSDo c диалект , но ответ для диалекта Closure Compiler или даже JSDo c сам был бы проницательным.

Я пытался (для TypeScript):

try { throw new Error(); } catch (/** @type {Error} */ e) {/*...*/}
try { throw new Error(); } /** @param {Error} e*/ catch (e) {/*...*/}
/** @param {Error} e*/ try { throw new Error(); } catch (e) {/*...*/}

Но безуспешно. e всегда имеет тип any. Будет работать

try { throw new Error(); } catch (_e) {
  /** @type {Error} */
  var e = _e;
  // ...
}

И дополнительная переменная будет оптимизирована с помощью расширенного режима компиляторов замыкания, но я считаю это громоздким и неоптимальным с точки зрения производительности (в сборке dev) и надеюсь, что есть лучший способ (т. е. тот, где мне не нужно создавать искусственную переменную только для того, чтобы аннотировать нужный тип).

1 Ответ

1 голос
/ 11 февраля 2020
try {throw new Error();} catch (/** @type {Error}*/whatIsMyType) {
  console.error(whatIsMyType.message);
}

Действителен в соответствии с Закрывающим компилятором .

Я не пишу много машинописи, но я искал несколько источников и в основном не вижу аннотаций на уровне catch. Те немногие, что я сделал см. , выглядели так:

try { throw new Error(); } catch (e: Error) {}

Обновление:

Я думаю, что TypeScript имеет право отказаться от гарантии типа для блока check. Вы можете выбросить что-либо (намеренно или иным образом) в блоке try, чтобы компилятор не мог гарантировать, что перехват пойман с правильным типом. В связанном ответе решение состоит в том, что вы должны проверить тип в catch:

try {
  throw new CustomError();
}
catch (err) {
  console.log('bing');
  if (err instanceof CustomError) {
    console.log(err.aPropThatIndeedExistsInCustomError); //works
    console.log(err.aPropThatDoesNotExistInCustomError); //error as expected
  } else {
    console.log(err); // this could still happen
  }
}

для ☝?

И я (и Роберт Мартин ) поощряю этот стиль проверки типов даже с сильными типами.

Обновление 2

Я переписал Пример сверху в синтаксис Closure Compiler, и я считаю, что точка остается в силе. Даже если Closure позволяет вам сделать определение из первого примера, вы, вероятно, не хотите (или, по крайней мере, не только):

class CustomError extends Error {
  constructor() {
    super();
    /** @type {string} */
    this.aPropThatIndeedExistsInCustomError = '';
    throw new Error('Not so fast!');  // The evil part is here
  }
}


try {
  throw new CustomError();
}
catch (/**  @type {CustomError} */err) {
  console.log('bing');
  if (err instanceof CustomError) {
    console.log(err.aPropThatIndeedExistsInCustomError); //works
    console.log(err.aPropThatDoesNotExistInCustomError); //error as expected
  } else {
    console.log(err); // this could still happen
  }
}

на closure-compiler.appspot

...