Dive into TypeScript to discover why function declarations and expressions infer types differently, using practical examples and clear explanations.
---
This video is based on the question https://stackoverflow.com/q/69971761/ asked by the user 'Chor' ( https://stackoverflow.com/u/10450891/ ) and on the answer https://stackoverflow.com/a/69971847/ provided by the user 'T.J. Crowder' ( https://stackoverflow.com/u/157247/ ) at 'Stack Overflow' website. Thanks to these great users and Stackexchange community for their contributions.
Visit these links for original content and any more details, such as alternate solutions, latest updates/developments on topic, comments, revision history etc. For example, the original title of the Question was: Why function expression and function declaration have different inference results for a variable?
Also, Content (except music) licensed under CC BY-SA https://meta.stackexchange.com/help/l...
The original Question post is licensed under the 'CC BY-SA 4.0' ( https://creativecommons.org/licenses/... ) license, and the original Answer post is licensed under the 'CC BY-SA 4.0' ( https://creativecommons.org/licenses/... ) license.
If anything seems off to you, please feel free to write me at vlogize [AT] gmail [DOT] com.
---
Understanding TypeScript Function Expressions vs Declarations: Why a Shows Different Types
When delving into TypeScript, especially regarding functions, you might encounter some puzzling type inference scenarios. A common source of confusion is the difference in type inference results for variables when used in function declarations compared to function expressions. In this guide, we'll explore this intriguing aspect of TypeScript and clarify why a, a variable initially declared as string | number, exhibits different behaviors within various function scopes.
The Scenario
Let's consider a simple example based on the following code snippet:
[[See Video to Reveal this Text or Code Snippet]]
Observations
When hovering over a in function b, its type is inferred as string | number.
In function c, a is inferred as number.
Similarly, in function d, a is also inferred as number.
This raises a crucial question: Why does b retain the possibility of a being string when it’s declared as a constant and holds a number at runtime?
The Explanation: Function Hoisting
The difference in type inference typically boils down to the concept of function hoisting. Let’s break it down:
What is Function Hoisting?
Function Hoisting: In JavaScript (and TypeScript), function declarations are hoisted to the top of their enclosing scope. This means that you can call them before they are defined in the code, allowing them to be invoked at any point after their declaration.
Applying Hoisting to Our Functions
Function b
When you declare function b, it can be called before the full initialization of variable a:
[[See Video to Reveal this Text or Code Snippet]]
From the type perspective, TypeScript doesn’t have the guarantee that a will always be assigned a number at the time b is called. Hence, it maintains a's type as string | number to account for any potential scenarios where a might not be raised yet.
Functions c and d
In contrast, both c and d are function expressions, which are not hoisted. You can't call them before they're defined. Therefore, once they're defined after a has been initialized to 3, TypeScript can safely infer that a is a number within the body of those functions:
[[See Video to Reveal this Text or Code Snippet]]
Conclusion
In summary, the difference in type inference for a across function declarations and expressions in TypeScript is a result of function hoisting. Function declarations allow TypeScript to consider the possibility of uninitialized variables since they can be invoked before their definition. On the other hand, function expressions can only be invoked after their definition, giving TypeScript the certainty needed to infer that a is a number at that point.
Understanding this distinction can greatly assist you in writing clearer, more effective TypeScript code and avoiding subtle bugs that may arise from misinterpreted types. Always keep in mind how hoisting can affect your type inference and overall function behavior.
Информация по комментариям в разработке