#typescript
#typescript
Вопрос:
Ошибка связана с сообщением, что левая / правая часть арифметической операции должна иметь тип ‘number’, ‘bigint’ и т. Д….
sort({ key, direction }: SortOptions<Listing>) {
this.dataSet.sort((a, b) => { // <--- dataSet: Listing[]
let returnVal;
if (typeof a[key] === 'number' amp;amp; typeof b[key] === 'number')
returnVal = a[key] - b[key]; // <-- error here
...
return direction === 'asc' ? returnVal : -returnVal;
});
}
для ключа уже проверен тип a keyof T
, где a и b имеют тип T.
interface SortOptions<T> {
key: keyof T;
direction: 'asc' | 'desc';
}
export interface Listing {
id: number;
title: string;
condition: string;
description: string;
price: number;
stock: number;
sold: boolean;
display: boolean;
}
Если я удалю проверку типа по ключу, т.е. SortOptions<Listing>
Ошибка не отображается. Но это потому, что тогда нет безопасности типов как key
есть any
, а a[key]
также any
Я знаю, что есть простые способы javascript, подобные a[key]
этой работе. Но я пытаюсь правильно проверить тип.
Комментарии:
1. Вероятно, потому, что typeof NaN также является «числом» :).
2. Вы можете извлечь
a[key]
иb[key]
к переменным, тогда typeguard будет работать3. @AlekseyL. у меня было ощущение, что это может быть ограничением компилятора. Знаете ли вы, почему? Кроме того, спасибо, не стесняйтесь оставлять ответ, я проголосую за него.
4. @AlekseyL. просто дикое предположение: геттеры в JS могут изменять значения, поэтому после запуска
typeof a[key] === 'number'
нет гарантииa[key]
, что они вернут то же значение в следующем операторе.5. @zerkms конечно, я понимаю, что ты говоришь. Я просто думаю, что это не связано с тем, почему
a[key] === 'number'
не работает. Если бы это было так — мой пример также не должен работать.
Ответ №1:
Известная проблема заключается в том, что TypeScript не во всех случаях выполняет сужение анализа потока управления при проверке свойств объекта. Некоторые отсутствующие в настоящее время варианты использования: проверка свойств на подписи индексов в квадратных скобках; проверка свойств на значения универсальных типов. Недавно были рассмотрены некоторые такие случаи, но, похоже, все еще существует пробел, если вы используете индексированный доступ к нелитеральному ключу. (Не уверен, к какой существующей проблеме, если таковая имеется, это относится). Я не уверен, что этот конкретный вариант использования когда-либо будет разрешен, поскольку предыдущие исправления приводили к снижению производительности.
В любом случае такое сужение защиты типа лучше работает с переменными, чем с выражениями переменных (например, с доступом к свойствам), поэтому, если вы сомневаетесь, разумным обходным путем является присвоение выражения, о котором вы заботитесь, его собственной переменной:
sort({ key, direction }: SortOptions<Listing>) {
this.dataSet.sort((a, b) => { // <--- dataSet: Listing[]
let returnVal;
const aKey = a[key]; // assign to new variable
const bKey = b[key]; // assign to new variable
if (typeof aKey === 'number' amp;amp; typeof bKey === 'number') // check variables
returnVal = aKey - bKey; // no error now
...
return direction === 'asc' ? returnVal : -returnVal;
});
}
Это должно работать так, как вы ожидаете. Надеюсь, это поможет; удачи!
Комментарии:
1. На самом деле это так , но не в этом конкретном случае
2. Да, спасибо. Литеральные ключи проверяются даже с помощью доступа к скобкам; Я отредактировал свой ответ, чтобы указать доступ к свойству для нелитерального индекса.
3. Спасибо, имеет смысл. Но теперь связанная проблема, похоже, не связана (и исправлена)
4. Хм, я думаю, что связанная проблема была связана, но они исправили только ее часть (или, по крайней мере, есть связанные проблемы, закрытые как дубликаты). Я спрошу, достаточно ли близки Microsoft / TypeScript # 28081 или Microsoft / TypeScript # 4742 или это отдельная проблема.
5. Это также может быть Microsoft / TypeScript #22214