Pull to refresh

Comments 10

Этот рисунок в коде превращается в кэш

Вычислив объект, нужный для работы программы, вы сталкиваетесь с характерным рисунком своих желаний

Это издёвка?

const cache = new Map< string, string >()
const item = cache.get( 'foo' ) ?? 'bar'

Не благодарите.

const cache = new Map< string, string >()
const cacheCopy = {...cache};
const item = cacheCopy.get( 'foo' ) ?? 'bar'

Ваш код напомнил замечательный пример из какого-то доклада где TS позволяет таки выстрелить себе в ногу - валидный с точки зрения типом код сломает runtime.

И все равно getItem, по мнению TypeScript, возвращает строку.

Я что-то не догоняю... Вы же явно указали тип string для элементов кеша:

const { getItem, setItem } = createCache<string>()

Естественно, теперь getItem возвращает только string, а как иначе? Хотите безопасную работу с null/undefined? createCache<string|null|undefined> (либо ваше решение, с встроенным undefined)

Хотите кеш с любыми типом значений? createCache<unknown>

Хотите выбрасывать ошибку для отсутствующих элементов? Добавьте проверку в реализацию методов.

Кроме того, в TypeScript есть куча настроек для уровня строгости типизации, просто далеко не все согласны выкручивать всё на максимум. Имхо, проблема высосана из пальца

Эта статья не про создание кэша. Рано или поздно вы столкнетесь с необходимостью доступа к элементу массива или свойству объекта с помощью квардтатных скобок и без знания особенности типизации можете рисковать (забыть проверить наличие элемента или выход за границы). Дело в том, что без флага компилятора TypeScript неверно выводит тип результата но считает, что даже если в массиве нет ни одного элемента то результат

Ведь если компилятор решит, что item это string, но не будет вас останавливать от действия

const items:string[] = [];//пустой массив
const item = items[0]; //item: string - а это неверно.
console.log(item.toUpperCase());// Нет ошибки без фалага noUncheckedIndexedAccess
//          ^^^^ Object is possibly 'undefined'. при наличии noUncheckedIndexedAccess

При наличии флага компилятор присвоит item:string|undefined. Это уже лучше. Если вы попробуете выполнить эти же действия с полученным значением (без проверки на undefinend), компилятор сообщит об ошибке. Тем самым попросит вас уточнить тип значения

Причем флаг влияет и на доступ к элементам массива, и на доступ к элементам объекта (по индексу)

TS не поддерживает завтипы, а значит вам придётся постоянно проверять на undefined, даже в тех случаях, когда никакого выхода за границы массива быть не может (большинство случаев корректного кода).

const items : string[] = [ 'foo' ]
const item = items[0]
if( item === undefined ) throw new Error( 'Matrix has you!' )
console.log( item.toUpperCase() )

for( let i = 0; i < items.length; i += 2 ) {
    const item = items[i]
    if( item === undefined ) throw new Error( 'Matrix has you!' )
    console.log( item.toUpperCase() )
}

Вы правы. TypeScript не волшебник и не дорос до зависимых типов (может ли вообще дорости имея корни в JavasScript?). Все хитрости JavaScript тянутся за ним хвостом. А стимулирует ли вас к проверке, как вы ее и написали, если вспомнить что часть элементов массива может остаться не инициализированной?

const items : string[] = [ 'foo' ];
items[4] = 'fifth';
const item = items[0]
if( typeof item === 'undefined' ) throw new Error( 'Matrix has you!' )
console.log( item.toUpperCase() )

for( let i = 0; i < items.length; i += 2 ) {
    const item = items[i]
    if( typeof item === 'undefined' ) continue;
    //без проверки - будет ошибка исполнения
    console.log( item.toUpperCase() )
}

Согласитесь, дело в том, что доступ по индексу и JavaScript может вернуть undefined на ровном месте

Достаточно сильная система типов может покрыть любые хитрости.

Дырявые массивы лучше не использовать. А если и использовать то типизировать элементы как предложили выше.

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

На практике, за много лет работы на крупных TypeScript-проектах, я, пожалуй, ни разу не сталкивался с вышеупомянутой ошибкой из-за выхода за границу массива.

Просто мне кажется, не стоит превращать TypeScript в Java, это не ускорит разработку. Хотите все плюшки строгой типизации - Java/C# + WebAssembly в руки, и вперёд :)

Sign up to leave a comment.

Articles