A scope is the set of all data which is available to a given context. A new, fresh scope is constructed for operational contexts—classes and functions—which allows those contexts to define their own data without polluting other scopes.
Within a JavaScript function, this would include all classes, functions, and variables which are defined directly within the function. TypeScript augments this with all type definitions made directly within the function.
However, an operational context does not have access to just its own scope; instead, it folds in access to the scope within which it was created, giving it access to the classes, functions, variables, and types that were known at its point of definition. Should a function make use of this outer scope, it is said to be a closure, for in uses the enclosing data.
Closures can provide a great degree of power, especially when used in the context of higher order functions and continuations, but can also prove to be stumbling blocks. In TypeScript, as in many languages, this is due to the enclosing scope being alterable.
When a function defines a new variable, that variable definition gets added to its scope. This can shadow similarly named variables defined within the outer scope, which is often desirable. (Programmers, being lazy efficient folk, tend to reuse identifiers for things that are roughly similar.) The variables defined locally—within the most recently defined scope—will behave according to that scopes restrictions, rather than how their outer context constrained them.
But should an outer scope variable be used without redefinition, its current value at the time the inner scope is evaluated will be used. Furthermore, the inner scope could, intentionally or not, modify variables defined in an outer scope, impacting contexts outside the function.
These state mutation concerns are typically considered undesirable side effects. Many developers strive, when programming functionally, to avoid side effects. Functions which do not edit outer scope state are said to be pure. This need not constrain the use of enclosing context, but it does require the developer to be cognizant of it and how they are interacting with it. Generally, this typically means inserting external state via extra parameters, or enclosing an immutable copy of the external state via a higher order function.
Pure functions, which do not alter state nor rely upon alterable state, are effectively idempotent: for the exact same inputs, they should return the exact same result. Sure functions are vastly easier to reason about and verify the correctness of their algorithms via testing.