Full expected it to error, and was pleasantly surprised to see it collapse into `never`.
@torickjdavis Жыл бұрын
@@HighlyVolkish 😅 Sorry, just interacting with the video and commented my answer.
@susantingebel4682 Жыл бұрын
because the never is the intersection of all bool, string and num
@profesor08 Жыл бұрын
Same problem as when you try to use function overloading. In implementation, you must indicate types for arguments to much all overloads.
@deshtechno Жыл бұрын
This is what always makes me feel that i'm doing something wrong like there is another better way to do this. For now I ended up checking type for typescript to be able to extract only one route and not mess my types.
@goodboyneon Жыл бұрын
I choose "no error" even though I knew typescript **should** error, just because Matt was pretty tricky on the last one!
@gerardmarquinarubio9492 Жыл бұрын
Sometimes it would be valuable to let type coercion work in this cases and you could type the parameter as Parameters[0].
@mateja176 Жыл бұрын
It should be possible to create an object which has all of the string properties, all of the number properties and all of the boolean properties. But in practice, one of the obstacles would be the + operator, since it doesn’t work outside the context of primitive numbers.
@hri7566 Жыл бұрын
type Cursed = Number & Boolean & String
@webblocksapp Жыл бұрын
Hey Matt, thanks for this video. It made me to remember another typescript situation related to union types, I would like to post my question here, may be you will want to elaborate it as another video. type UiComponents = { Accordions: Array; Buttons: Array; } const components: UiComponents = {Accordions: [], Buttons: []} const getComponent = (componentsName: T, id: UiComponents[T][number]['id']) => { return components[componentsName].find(item => item.id === id); //
@shadowplay1211 Жыл бұрын
I thought it wouldn't error, I thought the type of that parameter would be "number | string | boolean", it was surprising seeing it to collapse into "never" lol In this case I would give each function a generic parameter so I would be able to actually specify the exact type of that parameter later when executing the function
@modernkennnern Жыл бұрын
If it didn't that'd be crazy. This seems very obvious. It calls all 3 functions with 1 argument, so naturally that 1 argument has to match all 3 functions signatures
@bbarreir0153 Жыл бұрын
I can't really understand why people think it shouldn't error, just call the correct function for that type... It's clearly inside a loop, it WILL call EACH function with the same parameter... Obviously two of them will error, clear as day
@dasten123 Жыл бұрын
Why would one not expect an error there?
@mattpocockuk Жыл бұрын
I get this question a lot! So figured I'd do a video on it.
@artu-hnrq Жыл бұрын
I liked this format!
@lukeprinsloo301 Жыл бұрын
Awesome, Im still starting out with Typescript, this is all still new to me but I am starting to understand a little.
@ErwinVanLun Жыл бұрын
i hope it would, but I think he doesn't. I think the derived type of the argument will be string|boolean|number, so the error checking will pass
@roulzhq Жыл бұрын
Sure it will!
@juanpablodenis3748 Жыл бұрын
would setting myFuncs as const and checking the index on the map function make this work somehow?
@minnow1337 Жыл бұрын
func is typed as a union of the functions under myFunc so if you did that and compared equality between func and an index of myFunc yes it would work
@jeralm Жыл бұрын
Have you done a video on contravariance yet?
@bubble4525 Жыл бұрын
It is related to the concept of the "string &&number = never" in TypeScript????
@mattpocockuk Жыл бұрын
Yes!
@artur1998g Жыл бұрын
Oh I stumbled upon recently what you are talking about. I used rxjs and wrote some code, like. (isSomething ? of('test') : of(123)).pipe(tap((v) => console.log(v))) And I couldn't use the arguments in the pipe, because the type of the pipe is Observable | Observable.
@DavidBowmanJr Жыл бұрын
I bet my entire existance on a TypeScript error since 123 is neither a string nor boolean.
@antonpieper Жыл бұрын
This is actually how the UnionToIntersection type works
@aleksd286 Жыл бұрын
Would it still error if you would use index, and conditionally give it a proper type?
@mattpocockuk Жыл бұрын
Yep!
@aleksd286 Жыл бұрын
@@mattpocockuk Ok, that I would not have guessed :D, I thought it would've been fine with it. But what if you add as const?
@aleksd286 Жыл бұрын
I've checked and adding as const to the function array, doesn't make typescript realise that on index 0 fn will want a number, and on index 1 it's a string. const fns = [ (a: number) => {}, (b: string) => {}, ] as const; fns.map((fn, i) => { fn(i === 0 ? 1 : '1'); }) this kind of makes sense, but we're not on that level yet
@aleksd286 Жыл бұрын
const fns = [ (a: number) => {}, (b: string) => {}, ] as const; type Fns = typeof fns; fns.map((fn, i) => { type Fn = Fns[i]; const myFync: Fn = fn; myFync(i === 0 ? 1 : '1'); }) This ain't possible either, without the usage of Generic all hope is lost
@farahrayis5928 Жыл бұрын
"Put your life on the line!..." Haha. And I chose no, it was kinda obvious for me... Make more of these type of videos, they are so fun.
@ecmanaut Жыл бұрын
This made me finally dig into and figure out what the type of a function that DOES support all of the above formats looks like (doing different things, and each call style showing separate refdocs on hover), without having to use the parameter as the union of all in the one and only parameter list: ``` /** does something with a number */ function myFunc(a: number): void; /** does something with a string */ function myFunc(b: string): void; /** does something with a boolean */ function myFunc(c: boolean): void; function myFunc(x: number|string|boolean) {} ``` And to see what the legal types looks like, it turns out to be: ``` type F = typeof myFunc; // ^? // type F = { (a: number): void; (b: string): void; (c: boolean): void; } ```
@ecmanaut Жыл бұрын
This gets particularly useful in situations where you have a generic on an optional arg, which typescript is really stingy about allowing you to do with any kind of nice syntax, e g: ``` /** resolves to `value` after `milliseconds`, or `undefined`, if omitted */ export async function delay(milliseconds: number): Promise; export async function delay(milliseconds: number, value: V): Promise; export async function delay( milliseconds: number, value?: V ): Promise { return new Promise((resolve) => setTimeout(() => resolve(value), milliseconds) ); } type T = typeof delay; // ^? type T = { (milliseconds: number): Promise; (milliseconds: number, value: V): Promise; } ```
@ecmanaut Жыл бұрын
I'd LOVE a treatise on how to compose types like these with type helpers, as I've drawn a complete blank on how to do that, but find the need.
@minnow1337 Жыл бұрын
This if a feature of typescript called function overloading, which appears to be syntactical sugar for typing the function implementation as an object with method overloads for its call signature. I don’t think it’s possible to create a universal and useful utility type for something like defining overloads for a function with optional generic parameters, because you cannot know how many generic arguments the function you are deriving from accepts.
@karamuto1565 Жыл бұрын
That it errors was clear to me. But I didn't expect it to become never, but on second thought it makes sense.
@mudscuffer Жыл бұрын
I could tell that it should error, I thought and hoped it would error, but did not foresee the `never`.
@hugodsa89 Жыл бұрын
Yes beause the 123, is a number and doesn't suit the last two possible function declarations of myFuncs elements
@omri9325 Жыл бұрын
So the only reason to this video is to hype up for the TS 5.2 version?
@mattpocockuk Жыл бұрын
? No, this behaviour is the same for both versions.
@Luxcium Жыл бұрын
Can I get to see the tsconfig please???
@mattpocockuk Жыл бұрын
Assume strict true, that's basically it.
@mahadevovnl Жыл бұрын
That seems like an error in TS, then? It shouldn't make it into a union, it should be string OR number OR boolean, then the code would remain intuitive and you wouldn't have to add verbose code to the function mapper where you have to solve an issue that TS created. Or is there some benefit to this that I'm missing? I can imagine that in a tuple it would be super annoying, too.
@BraedenSmith Жыл бұрын
It's not OR, it's the intersection (AND) of those types.
@mahadevovnl Жыл бұрын
@@BraedenSmith Yes I know, and I'm saying it should be different,
@modernkennnern Жыл бұрын
This would call all of these methods with the same argument, so that singular argument would have to be valid for all 3 functions, which is impossible
@MrPeepa Жыл бұрын
I dont know what use case that would apply to, but wouldnt it be better to do ` myFunc: ( a : number | string | boolean ) => void; ` ??
@minnow1337 Жыл бұрын
He is just making a demonstration to help us understand typescript behavior. There probably isn’t a practical use case, or at least it would be very niche. You are supposed to assume that you cannot change the type of myFunc because it derives its type from the functions stored within it. You would be introducing bugs into your code just to satisfy the typescript compiler. The only solution besides checking the types of the functions before they are executed is what he showed.
@mattshnoop Жыл бұрын
Maybe semantics, but I would say the functions are being "intersectioned" instead of being "unioned" together 😉
@mattpocockuk Жыл бұрын
The functions are being unioned together, but the parameter gets intersectioned because of that.
@mattshnoop Жыл бұрын
@@mattpocockuk Ah, right! I should have tested in the playground before trying to be a smartypants 😅
@loic.bertrand Жыл бұрын
Can I say also that the code in the thumbnail will error too because it's a const without initializer ? x)
@mattpocockuk Жыл бұрын
Imagine it's a declare const, but I didn't want to add 'declare' in the thumbnail.
@merveillevaneck5906 Жыл бұрын
Cool now please make a follow up on what to do when you’re in that situation 😂
@mattpocockuk Жыл бұрын
'as never' probably
@anthonfredriksson5633 Жыл бұрын
I expected it not to error because I thought TS would make func take a parameter which is a union of number | string | boolean and a number satisfies that. 😢
@minnow1337 Жыл бұрын
typescript doesn’t allow for implicit type coercion, which is actually a feature of javascript.
@samculo1051 Жыл бұрын
Awesome and useful content
@juliohintze595 Жыл бұрын
I would be pissed if it didn't error.
@mdkawsarislamyeasin4040 Жыл бұрын
Still confused 😅😐
@fulconandroadcone9488 Жыл бұрын
My sanity depends on this being yes.
@mikopiko Жыл бұрын
You solve this case by pattern matching.
@coding-master-shayan Жыл бұрын
Yes it will throw error because type number is not assignable to type string
@somchai.sinsatianpawn7 ай бұрын
yes
@artur1998g Жыл бұрын
yes
@epotnwarlock Жыл бұрын
Am i the only one totally confused as to why people love how bizarre js/ts is, like why would you do this?
@chidigideon8224 Жыл бұрын
Yes
@Noam-Bahar Жыл бұрын
Will error
@dankow325710 ай бұрын
no error
@mantassidabras2921 Жыл бұрын
No!!!
@kevin5523 Жыл бұрын
no
@paulsanchez5030 Жыл бұрын
Yes it will error, life on the line.
@alexeyl1739 Жыл бұрын
It will error.
@aaronabuusama Жыл бұрын
yes but i have a feeling this is a trick
@kaos666999 Жыл бұрын
No error
@coding-master-shayan Жыл бұрын
What 😮
@dog4ik Жыл бұрын
I hope it will error
@jurijzahn8985 Жыл бұрын
Yeah function params are covariant. And this is the basis for the famous UnionToIntersection type helper. 😁