Один из способов, чтобы это работало, состоял бы в том, чтобы компилятор встраивал некоторые вызовы функций при выполнении анализа потока управления, что означает, что это:
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
, и переходить к другим вещам.
Хорошо, надеюсь, это поможет вам. Удачи!
person
jcalz
schedule
27.09.2019