Я бы сделал это с псевдонимом типа:
type SaferArray<T> = Array<T | undefined>;
const example: SaferArray<string> = ["hello"];
const a = example[0]; // string | undefined
const b = example[1]; // string | undefined
Можно расширить, если хотите. Вам просто не хватает | undefined
в расширяемом типе:
interface SaferArray<T> extends Array<T | undefined> {
[i: number]: T | undefined
}