Предикаты типа в TypeScript - PullRequest
       21

Предикаты типа в TypeScript

1 голос
/ 27 сентября 2019

Это недостаток функции в TypeScript или что-то хорошо продуманное, что TS-компилятор не может определить (и затем сузить) тип аргумента, если логика условия заключена в отдельную функцию?Что я имею в виду, так это то, что TS-компилятор дает мне ошибку в этом случае:

function isString(s) {
  return typeof s === 'string';
}

function toUpperCase(x: unknown) {
  if(isString(x)) {
    x.toUpperCase(); // ⚡️ x is still of type unknown
  }
}

Однако, если я избавлюсь от функции isString и добавлю ее логику в оператор if, то компилятор TS узнаетвведите хорошо.

Я знаю, что могу привести тип, используя as string или использовать предикаты типа и использовать аннотацию типа is string в функции isString.Но я только начал задумываться - почему ТС не может сузить тип x.

1 Ответ

2 голосов
/ 27 сентября 2019

Один из способов для этого был бы, если бы компилятор включил некоторые вызовы функций при выполнении анализа потока управления, что означает, что это:

function toUpperCase(x: unknown) {
  if (isString(x)) {
     x.toUpperCase(); 
  }
}

необходимо будет проанализировать так, как если бы тело isString()были расширены следующим образом:

function toUpperCase(x: unknown) {
  if (typeof x === "string") {
    x.toUpperCase();
  }
}

Каноническая проблема в GitHub, говорящая об этом: microsoft / TypeScript # 9998 .Вопрос, который задают в этом выпуске: «Когда вызывается функция, как мы должны предполагать ее побочные эффекты?»И, кажется, нет идеальных ответов.Говорят, что полное встроенное решение для всех вызовов функций "не будет даже практически удаленным". Может ли быть поверхностное встраивание, которое ведет себя так, как вы хотите для isString(), не затопляя компилятор полностью?Возможно, но стоит ли это того?Точно сказать не могу.Не похоже, что там достигнут большой прогресс;если вы чувствуете в этом достаточно сильные мысли и у вас есть интересные идеи, вы можете внести свой вклад в проблему GitHub.


Еще один способ для этого будет, если компилятор автоматически выведет предикаты типов возвращаемых типов для правильных типов boolean -возвратных функций, что означает следующее:

function isString(s: unknown) {
  return typeof s === "string";
}

необходимо сделать вывод, как если бы это было так:

function isString(s: unknown): s is string {
  return typeof s === "string";
}

Каноническая проблема в GitHub, говорящая об этом, - microsoft / TypeScript # 16069 .Предыдущая версия этого была отклонена как слишком сложная , потому что, опять же, для компилятора нецелесообразно анализировать каждую функцию, возвращающую логическое значение, и выяснять, есть ли какие-либо последствия типа предиката типадля его типа возврата.Тем не менее, # 16069 все еще открыт, предположительно с намерением собрать низко висящий плод «простых» функций, таких как x => typeof x === "string".И опять же, неясно, достигнут ли там какой-либо прогресс, поэтому, если вы чувствуете в этом достаточно решительные идеи и у вас есть некоторые убедительные идеи, вы можете внести свой вклад в проблему GitHub.


Но ни в одном из этих случаев я не задержал бы дыхание на вашем месте.Идиоматическим решением для TS3.6 было бы просто аннотировать isString() как определяемый пользователем тип защиты, возвращающий s is string, и переходить к другим вещам.

Хорошо, надеюсь, это поможет вам.Удачи!

...