Home > Software engineering >  Why function expression and function declaration have different inference results for a variable?
Why function expression and function declaration have different inference results for a variable?

Time:11-15

I have a variable and three function:

const a: string | number = 3

function b(){
  console.log(a)               // string | number 
}
const c = function (){
  console.log(a)               // number
}
const d = () => {
  console.log(a)               // number
}

When I hovered the word a in function b, what I got is string | number;

When I hovered the word a in function c, what I got is number;

When I hovered the word a in function d, what I got is number

But isn't a a constant? After the first time it was assigned the value 3, a have been infered to become a number type. Why in function b it still have a chance to become a string type?

CodePudding user response:

I believe it's because of function hoisting. In theory, b could be called before a has its value definitely assigned:

b(); // <=====
const a: string | number = 3

function b(){
  console.log(a)               // string | number 
}
const c = function (){
  console.log(a)               // number
}
const d = () => {
  console.log(a)               // number
}

Neither c nor d can be called from there, they aren't assigned until after a is definitely assigned.

From a runtime perspective, the call to b would throw when trying to access a because a would be in the temporal dead zone, but from a type perspective, it would be before TypeScript knew it was a number.

CodePudding user response:

Probably because in JS/TS, functions' names (and types) are declared before any values are assigned to variables/constants. At the time function b's type is evaluated, only the declared type of a is known, i.e. string | number. By the time c and d are assigned to, a is known to be a constant number value of 3.

CodePudding user response:

In js, functions are first-class citizens, so functions directly declared in js will be brought to the forefront. If you try the following code, all as will prompt string | number, online

function b(){
  console.log(a)               // string | number 
}
const c = function (){
  console.log(a)               // string | number 
}
const d = () => {
  console.log(a)               // string | number 
}
const a: string | number = 3
  • Related