Why is noUncheckedIndexedAccess enabled by default?
I started a project using
create-t3-app
and I was getting all these type checker errors throughout my code, which forced me to manually reassert types all over the place. Setting "noUncheckedIndexedAccess": false
in tsconfig.json
solved the problem with my type checker but I'm left wondering why this was enabled by default in the first place. Manually reassert types all over the place seems to run contrary to this discussion: https://www.youtube.com/watch?v=RmGHnYUqQ4kTheo - ping․gg
YouTube
You Might Be Using Typescript Wrong...
I'm getting increasingly tired of the "but TS is so much woooooork" comments so I figured I'd do a rant.
If you have friends or coworkers who are using Typescript incorrectly, please send this video to them :)
Also please use Zod more it's very good https://github.com/colinhacks/zod
Join the Discord: https://t3.gg/discord
Follow me on Twitter...
32 Replies
The rule doesn't exist just so you can non-null-assert everything, it's to protect you from accessing elements which doesn't exist.
@julius so why does it exist? Is there a way to resolve this issue while
noUncheckedIndexedAccess": true
? https://stackoverflow.com/questions/74503582/defined-value-giving-object-is-possibly-undefined-how-to-avoid-manually-re/74503695#74503695Stack Overflow
Defined Value Giving: Object is possibly 'undefined'`. How to Avoid...
In this function, I am getting a type error from VS Code. The error refers to board[0]. The error states Object is possibly 'undefined' which refers to`
export default function validPosition(board...
Well even if array.length > 1 doesnt mean array[1] exists,
Unless I'm mistaken it's there because it's seen as a safe and sensible default. Otherwise you can access values outside of the array's bounds and have an
undefined
value that TS tells you is truthy.
Or, more accurately, that the compiler tells you is whatever value you typed the array as.
Is it more upkeep? Yes. But TS, itself, involves more upkeep than JS. That doesn't mean it doesn't have value and won't save you from bugs.I can have array = [1,2,3,4] and without noUncheckedIndexAccess, array[100] would give me the type number
The way I typed with zod, if you do
board[0]
there will always be a number there no?typeof
gives you the correct type, at runtime. We're talking about the typing as presented by the compiler, before run.
That's why a solution to narrow that type would be to check if (typeof arr[0] === ///)
So in the situation where we believe it is prudent to use
noUncheckedIndexedAccess": true
, what is the preferred way to to satisfy the type checker without having to do null checks and / or manual type accessions as discribed in the stackoverflow issue I linkedI'm curious to hear how others prefer to handle that conveniently, myself.
TS Playground - An online editor for exploring TypeScript and JavaS...
The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.
that depends on what you want to fallback to, some alternatives:
then there are cases where you know for example arr[0] is valid, then a non-null-assertion can be fine
I guess I'm trying to type it rigorously so that I don't have to configure a fallback. Maybe that's impossible or impractical?
there's no typesafe way unless you check
Well I feel like what ever logic I'm using in my head to detemine that I "know" should be able to be baked into the type system...
you got an example?
Yeah, the one I linked is an example. It is impossible for
board[0]
to ever be undefined
board is being created from a static json file. there is not dynamic user input or api. it's loaded locally.
The structure is validated by zod and there is always something there, a number.
I'm sorry perhaps I'm not understandingyour zod validator doesn't guarantee board[0] is defined, it validates that the array's length is > 0
counter example right here
Generally it's not a good idea to try and get around the compiler because of what you "know". Certainly those times exist (non-null assertions are there for a reason), but in general the reason the compiler is there is to force you to "do your homework" so you don't have to rely on your own fallible understanding of the program's types.
If "I know the types" were a good enough solution, TS wouldn't be useful.
I like how this discussion is turning into discrete math proofs 😄 (jk)
It can be grating writing extra conditions to go-behind when you're pretty positive. But if the state of your app changes in the future, it may end up saving you from an insidious bug.
Yeah, this is my point exactly.
https://github.com/currenthandle/mine-sweeper/blob/add-reducer/src/utils/validators.ts
Sure but whose to say you dont call that function before the grid is validated, or the grid’s been mutated after validation and before the function call
well, the grid never mutates, and I've written it so that it is the very first thing that happens. ie it won't get called before the grid is validated. So now the issue at hand is, how can I bake these facts (or the equivelent) into the type system.
a simple
if (!board[0]) return false;
is probably what i’d doyeah so now were back to null checks i guess...
just feels hacky + adding extra lines of code
Idk bout that, you’re protecting against future mistakes. You may remember this today but in a week you might refactor without remebering these 3 mental steps in your head
If you think thats overhead then turn off the rule, im just trying to explain its usefulness
Particularly when working with others who may not have the same understanding about the conventions of the base, it's an extra safeguard and future-proofing.
Strangely enough after resetting
"noUncheckedIndexedAccess": true
in my tsconfig, there is no more TS Object possibly undefined....
err in this file/function 🤦
Instead I'm getting 'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
in my components all the sudden and it's asking me to import React from 'react'
in each component file explicitly. I've never seen this before with create-t3-app
Are you sure you didn't change anything else in your tsconfig? Maybe the
jsx
property?"jsx": "preserve",
same as in my other create-t3-app projects