Следующий код
const s: string[] = ["x", "y", "z"].map(i => ["x"].find(t => t === i));
Это вызывает ошибку «Тип '(string | undefined)[]' нельзя присвоить типу 'string[]'.», поскольку find
дает string | undefined
. Поэтому я надеялся, что добавление фильтра может исправить это, например:
const s: string[] = ["x", "y", "z"].map(i => ["x"].find(t => t === i)).filter(i => i);
Но это не сработало, почему?
ТС версии 4.2.3
Или, может быть, stackoverflow.com/q/63541843/3001761
Если вы точно знаете, что вызов find
здесь вернет никогдаundefined
, вы можете использовать утверждение с '!':
const s: string[] = ["x", "y", "z"].map(i => ["x"].find(t => t === i)!);
// ^
В противном случае вам придется написать охрану:
function isDefinitelyAString(val: unknown): val is string {
return typeof val === "string";
}
const s: string[] = ["x", "y", "z"].map(i => ["x"].find(t => t === i)).filter(isDefinitelyAString);
Вы также можете встроить охрану, как предлагает @jonrsharpe:
const s: string[] = ["x", "y", "z"].map(i => ["x"].find(t => t === i)).filter((i): i is string => typeof i === "string");
Обратите внимание, что .filter((i): i is string => i)
сам по себе не подходит, потому что только логические значения совместимы с предикатами типа.
Я просто хочу добавить, что оператор !
всегда опасен, поэтому, если есть какое-то решение, чтобы избежать его, вы должны это сделать. Гвардия будет лучше на 100%
Вот почему я сказал, что если вы знаете наверняка, то вы можете использовать это, но все же это рискованно.
@jonrsharpe Да, хороший улов, я обновил его, спасибо.
Спасибо, это быстро! Почему я не могу просто добавить! до конца filter
?
'!' утверждает, что предыдущее выражение не может быть неопределенным или нулевым. После фильтра тип (string | undefined)[] и поэтому работать не будет.
Я заменил typeof i === "string"
на !!i
TypeScript не выведет предикат типа, поможет
.filter((i): i is string =>
.