I resonate with your approach so much more than other TS youtubers.
@smorebytes Жыл бұрын
Thanks for your thoughts. Always love hearing the fundamental perspective of other developers.
@pastenml Жыл бұрын
I find it very hard to be able to escape `as`. For example fetching JSON from an API where you know the shape they are in, working with the dom and events (event.target), using libraries that are poorly typed (like the chromecast types on definitelytyped which are both incomplete and wrong).
@allan4386 Жыл бұрын
I've found validating those 'unknown' types to be a good way to handle those cases, with something like zod
@doremicocoparis9410 Жыл бұрын
Yeah I use zod for this, trust but verify
@necrifed Жыл бұрын
Everyday I hate typescript more 😂
@Guergeiro Жыл бұрын
I also use your approach and try to avoid `!` or the `as` keyword as much as possible, but one thing that people normally forget to mention is, with the examples you gave (isMember, assertsMember, isNotNull) or type checking/narrowing is general, that you are introducing runtime behaviour to fix a compile time problem. That type checking/narrowing doesn't come for free and sometimes I see people checking deeply nested properties and such just to get to the type that satisfies TypeScript enough. You are correct in that one normally relies on these checks when at the edge of the system, but even then, although I understand safe guarding against client code, I think that when you are in control of a specific end to end edge of the system, I would argue `!` and `as` to be a nice way to save some cycles! Great vid btw! Keep at it!
@yunk_gaming Жыл бұрын
I agree. Knowing when to reach for these tools is an important lesson. Using 'as' or ! can simplify things, but makes your code less typesafe and may introduce bugs. If I know for certain that `array.find` will return an item, it may make sense to "cast" the result (usually to save time so I can finish the feature working on). However, I might kick myself later if an edge case happens to return undefined.
@antonpieper Жыл бұрын
"Micro optimization is the root of all evil" ironically I do that kind of assertion in my code as well when I 100% know that it is safe because all other variables are controlled and safe
@Guergeiro Жыл бұрын
@@antonpieper it's not micro optimization if you're doing these checks inside a .reduce for example. Of course it depends, but the point I'm trying to make here is that we are solving a compiler problem by introducing runtime behaviour and almost no one mentions the bad parts, only good parts.
@amans6504 Жыл бұрын
We are over killing it with those runtimes checks. Just ship and move. Developer efficiency is more important.
@doremicocoparis9410 Жыл бұрын
How is fixing bugs caused by type unsoundness good for developer productivity?
Жыл бұрын
for `findOrThrow`, a safer way to write the function would be `if (t === null) {...}` since we might be looking for something that resolves to 0.
@zacbackas Жыл бұрын
To check for undefined wouldn't you want `== null` instead?
@andrew-burgess Жыл бұрын
yep, `t == null` would definitely be a better way to do this, good callout!
@kbsanders Жыл бұрын
6:16 Same caveat applies for line 17 and 24 (!!arg)
@kbsanders Жыл бұрын
I guess line 17 is OK, since you're ultimately drilling down into an object.
Жыл бұрын
@@zacbackas I thought `Array.find` returned null when it did not match any results, but it does seem to return undefined so you're right. I guess you could even triple equal for undefined.
@meyou118 Жыл бұрын
good advise - thx
@ness-ee Жыл бұрын
Another one of your videos that I’ll show to the team.
@RobertKonigsberg Жыл бұрын
`asserts arg is Type` is new to me. Very nice.
@tzuilee588 Жыл бұрын
Your explanation is so good! 😁
@ThaRealIansanity Жыл бұрын
Thanks. I 've been trying to figure out how to deal with a complicated union of types returned from a nuxt composable. I think these methods will help.
@gosnooky Жыл бұрын
Just a question not related to the topic - what is with your font? At 4:53, the "find" part looks squished, as if a fixed-width font has some variable-width characters. It's very strange and I'm just curious.
@edgeeffect5 ай бұрын
I've found myself a few times needing to do `as unknown as SomethingElse` and that leaves a horrible smell in the room... but, at my current stage, I don't see any way around it.
@killymxi Жыл бұрын
Checked where I'm using it: import/export { foo as bar }; [] as T[]; {} as T when {} is a valid instance of T; Some situation with co/contra variance in higher order function overloading; Some situation when composing multiple generic higher order functions and it is too difficult for TS to infer the correct (still generic) type. Thanks to this video, I realized I no longer need some other instances of 'as' in my code and there is one more I can potentially remove by improving a type definition and allowing TS to generalize all argument types to a common type.
@killymxi Жыл бұрын
Just added several more instances to my code, after a user reported an issue that turned out to be a bad passed value in JS client code: - an input validation "!(typeof str === 'string' || (str as unknown) instanceof String)", because TS is not happy about instanceof after a "known" type; - a test with "as unknows as T" that expects a throw in case of invalid input.
@5argan Жыл бұрын
For your first example, I use "const Foo: T[] =[];" instead
@najlepszyinformatyk1661 Жыл бұрын
What is the difference between just const and declare const?
@gordonfreimann Жыл бұрын
I couldn't help but notice the color of your ears change as the video progresses. On the other hand I really enjoyed the video and I think it is very helpful.
@ricko13 Жыл бұрын
can you guys imagine the amount of hours this guy has put into typescript to get to where he is now? As a beginner myself, I feel like he's speaking chinese
@QckSGaming Жыл бұрын
Really just a few projects after a solid programming (not javascripting) background of some years. Generally languages have types so Typescript is pretty self-explanatory and you can see and learn the Typescript-isms when you google for common stuff like "typescript assert type is not *"
@ricko13 Жыл бұрын
@@QckSGaming well, kinda... if you really want to master this thing you gotta spend a lot of time working on it
@moodynoob Жыл бұрын
@@ricko13 You're correct, you need to go down the rabbit hole to truly make the most of Typescript (or if you maintain libraries). I use Typescript to encode actual business logic, and its cool to see multiple files full of types that will never make it to the user, but catch incorrect logic for my context.
@andrew-burgess Жыл бұрын
@potato super-curious to see an example of how you encode business logic in TS, if you have one you can share!
@magicbob8 Жыл бұрын
This is a great video!
@neilpadfield Жыл бұрын
I find that `as` is sometimes necessary in certain generic functions or classes where it is 100% certain that something has to be a specific time, but the compiler can't work that out, so you have to tell it.
@Azoraqua Жыл бұрын
You can cast an object (Perhaps even an array) using generics. ``` type Person = { name: string, age: number, } const person = { name: 'John', age: 47, }; ``` Personally, I like this syntax quite a lot however it's effectively the same as `person: Person`. unlike `as` which doesn't force said format.
@guillaumebrunerie Жыл бұрын
This has nothing to do with generics, this is just an alternative syntax to using "as". And it's recommended not to use this syntax anymore as it does not work with tsx.
@Azoraqua Жыл бұрын
@@guillaumebrunerie It’s different to the ‘as’ syntax because when using ‘as’ you’re overriding whatever the type is whilst that kinda generic-like syntax enforces said format instead of transforming it into another. Beyond that, I think it’s a decent option if you do not want to use ‘as’. In regard to lack of support with TSX, that’s only mildly inconvenient as you do not have to mix TS and TSX in the same files at all times.
@hynekss8618 Жыл бұрын
@@guillaumebrunerie It can be used in a tsx file, but you need to append a trailing comma, e.g., `const person = (...) {...}`
@wtl9128 ай бұрын
Excellent video, thanks a lot! Btw, it'd be great if you have the chance to add timestamps to your videos, it really helps a lot!
@me_rinta Жыл бұрын
Why do you use “declare” for the first two statements?
@andrew-burgess Жыл бұрын
It's a way to declare a variable of a given type in TS without needing to provide a value for it. I think of it as saying "suppose I have some variable called X of type Y" and then you can use X to see how it interacts with your types.
@oscarcastillejo9685 Жыл бұрын
Another way to see the “as const” is to declare a literal
@aram5642 Жыл бұрын
`As` soon `as`... (pun intended!) one needs to use .querySelector combined with other DOM methods they become friends with `as`. Every HTML element has typically an inheritance hierarchy of at least 3 levels: Node, Element, HTMLElement, and so on. Depending on where you need the result you might have to use `as` to achieve a proper coercion. As for `asserts something is Something` - I personally avoid these, for exactly the same reason you mention: there is never a 100% certainty, and if so - I would like to avoid throwing errors.
@whotao6259 Жыл бұрын
I like to to use `function isNotNull(x: T): x is NonNullable` !
@wavecoders Жыл бұрын
Just add || 0 at the end of your find statement and if undefined it will make the return 0 as default
@artist6000ish Жыл бұрын
Casting comes from 'C. It's not a runtime behavior. idk where you get that casting is a runtime behavior.
@KirkWaiblinger Жыл бұрын
Just use a general assertion function to assert it's not null. Then you get narrowing. Declare function assert(x: unknown): asserts x; assert(x != null) This also doesn't address the common (anti)pattern of type widening assertions. const myRef = ref(null as null | HtmlElement); This is better to workaround with const myRef = ref(null)
@pawekoaczynski4505 Жыл бұрын
I use `as` in tests, when I don't want to pass all the fields of a type in a particular test. I never use `as` outside test (obviously, excluding the `as const`). Also, that `isMember` function might lie to you in the future. Let's say, two weeks later, somebody adds field 'foo'. And you don't update the `isMember` function. In that case, the function wil lie. The problem is that both `as` and `is` are a programmer's promise that the they know better than the compiler. In order to be 100% sure, you have to use a library like zod. The problem is, that it might be too heavy to be used in the browser
@i.j.5513 Жыл бұрын
++ On the need to use assertions for when we are dealing with poorly typed 3rd party libraries. They could be typed to return any, but it is clear from the source code or documentation that they should return a string. You use the assertion there, because you're not really trying to test the 3rd party library code correctness. Why you would need to use that poorly typed 3rd party library or if there is an alternative to use --- that's a different question.
@mk72v2oq Жыл бұрын
Enable "noUncheckedIndexedAccess" compiler option for your codebase and enter a whole new world xD
@amans6504 Жыл бұрын
We eventually need rutime checks at many such places
@camotubi Жыл бұрын
Me yolo swaging with "as unknown as T"
@kevduc314 Жыл бұрын
Could you also make a similar video about using truthy/falsy values? 😄 They can sometimes be handy (e.g. `.filter(Boolean)`) but in general should probably be avoided because of how unreliable they are: e.g. in your code you used `!!` a few times, and it's especially deceptive when used with primitive types other than objects, like in isNotNull, that would actually return false if the input is the number 0 or empty string "", when what you really want is something that is neither null nor undefined. In general explicit checks with operators that don't coerce values to truthy/falsy are much safer, in this case explicitly checking for null or undefined with `!==` would be the way to go, `arg !== null && arg !== undefined`. And in that case TS doesn't save you from this JS mess that truthy/falsy values are: TS doesn't have more granular union exclusions on primitive types like string and number, e.g. it won't show you that by checking !!arg for a string, the resulting type for isNotNull would be something like `Exclude`, that just gets simplified to `string`, which doesn't help you catch the issue!
@ness-ee Жыл бұрын
I was wondering why he left that !!arg in. I’m gonna go and log out !!0 now to see. Ok I’m back. It’s false; so is an empty string. Tut tut
@yfzhangphonn Жыл бұрын
That's when you need Functional programming. ^^
@KlethonioFerreira4 ай бұрын
There is react-router-dom, it's challenging....
@FunctionGermany Жыл бұрын
9:00 zod
@hugodsa89 Жыл бұрын
100% not using ! or as, the amount of times I’ve seen bugs because people way up in the code create these assumptions and then I’m going through issues that are blatant lies to the transpiler
@tahasoft1 Жыл бұрын
I use this function export function assertIsDefined(x: T): asserts x is NonNullable { if (x === undefined || x === null) { throw new Error(`${Object.keys({ val: x })[0]} undefined`); } } for all places I want to assert something is not undefined or null for example const member = members.find(m => m.id === 1) assertIsDefined(member)
@curiositycrateyt Жыл бұрын
so basically I used to do it correctly in just JS then with TS i got sloppy, and now im doing more boilerplate code in TS just for autocomplete
@eJuniorA2 Жыл бұрын
By your logic the compiler is mistakenly misleading you by not throwing errors all around everytime you are using an Array or Record. Or by not forcing you handling throwed errors. Typescript has all kinds of hypocrite and conflicting assumptions all around wich we learn to handle. Sometimes you know MORE information than the compiler, you shouldnt throw away better knowledge "just in case you could be wrong" or for the sake of a "pattern". More knowledge is always better.
@Yutaro-Yoshii Жыл бұрын
I am kind of annoyed that typescript doesn't complain about using literal index that might not exist on an array. If this is the case, then they should not complain about calling members.find with a non-existent id.
@BraedenSmith Жыл бұрын
Agree this should be the default, but you can turn it on via noUncheckedIndexAccess.
@guillaumebrunerie Жыл бұрын
It does, just use the --noUncheckedIndexedAccess option.