Proposal: propagate function context into the 'this' type of functions #23554
Labels
Declined
The issue was declined as something which matches the TypeScript vision
Suggestion
An idea for TypeScript
Problem
TypeScript's type system is bad at preserving type information of transformed types (such as those created with the
readonly
modifier)Examples of Current Behavior
Losing
readonly
ModifiersCalling Functions Which Are Ignorant of
readonly
ModifiersCalling functions with possibly undefined values with
strictNullChecks
These problems are caused because functions are context agnostic.
The first problem can be solved as a specific case in a few different ways.
These solutions are insufficient because they require
readonly
property.What Makes a Context Different
There are currently only 2 modifiers to a type in TypeScript
readonly
which marks a property as read-only, but does not change assignability.?
which marks the existence of the property as optional.JavaScript also allows any function to be called with any context with the
Function#call
,Function#bind
, andFunction#apply
commands. There is no current enforcement in the type system that these are valid calls.Core Proposal
To solve these issues, a function must be able to give more control over its context; and for this to be viable in large projects, the allowable context must be determinable by the type checker.
The Implementation Solution
When an implementation of a function is known, determining the context's from which it can be called should be fairly trivial for the type checker. A brief overview of what that would look like:
this
value is never used, then the context can beany
.this
, determine if the member is accessed, add it to a set of read members.2.1. If it was read in a way that would be legal if it were an optional member, then add it to the optional set.
2.2. Determine if the member is written to, add it to set of written members.
The Declaration Solution
Declaration files not generated by the type checker would be able to (and already can) add their own explicit context to a function. While the type checker has the opportunity to be very detailed in the required context, a hand-curated declarations file would be best served by using more broad strokes, such as:
this
In GenericsCurrently the
this
type cannot be used in theConstraint
portion of a genericTypeParameter
. This would need to not be the case for this implementation to work in the wild.When the keyword
this
appears as theBindingIdentifier
in aTypeParameter
it is shorthand for the following:The reason for not just using the equivalent is because the
this extends T
allows the type checker to also assert thatthis
extendsT
, which is confusing only because of the heavy use ofthis
. A few examples:In that example
goodFunc
is using the already existing method of marking an explicitthis
type for a function.The
this extends Partial<RandomInterface>
could have been written asthis extends Partial<this>
for the same meaning.Compiler Flag
Because this change could cause existing code to not compile, it should be added behind a compiler flag
strictContextChecks
, this would affect if the declarations files that are output from implementations would include this context, also if the compiler was adding them implicitly for type checking a single project.JavaScript Emit
None of the proposed changes would have any effect on the JavaScript emit.
Additional Comments
Until
readonly a: number
is not assignable toa: number
then most issues with readonly are not solvable in a satisfying way.Related Issues
readonly
type operator to allow correct definition ofObject.freeze
#10725The text was updated successfully, but these errors were encountered: