You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[isolatedDeclarations][5.5] Adding satisfies to a const expression makes it require explicit type annotationΒ #58397
My impression was that satisfies may impact the contextual type of an expression and cause its type to change, such that its type may not be syntactically inferable. (Need to dig up that example again, though.)
My impression was that satisfies may impact the contextual type of an expression and cause its type to change, such that its type may not be syntactically inferable. (Need to dig up that example again, though.)
Yep I've definitely seen cases where satisfies influences the contextual type of an expression, but I wonder if the as const + direct assignment to a variable is a sufficiently well-defined scenario that we can always trivially extract the type.
I wonder if the problem boils down to it not being possible to determine whether the const inference of an expression or the satisfies inference or combination of the two leads to the more specific type, then can we defer that decision down the line, so that
Are there cases where knowing only the const inference of an expression + the satisfies type constraint isn't sufficient to determine the contextually inferred type?
Forgive me for pushing on this, as I'm sure folks are eager to treat this as an open and shut case. We have hundreds of instances of this pattern in our code base, the majority in which are cases where satisfies wouldn't affect the contextually inferred type. We adopted the operator early on under a different assumption
The new satisfies operator lets us validate that the type of an expression matches some type, without changing the resulting type of that expression[0]
So while we could migrate back to our old pattern (since duplicating the structure of the expression with an explicit type is the less desirable option) of doing a type test like
satisfies invoking contextual typing is a necessary evil imo; you want e.g. [42] satisfies [number] to succeed, but for that you need to contextually type [42] by [number] so that it doesn't widen to an array type before it can be checked. But that in turn means that [42] ultimately gets inferred as a tuple type instead of an array type. There's no mechanism to "reverse" that after-the-fact because it actually changes which type is initially inferred for the expression.
There's a general class of "operations that non-trivially affect the actual type", including but not limited to:
satisfies
... ? ... : ...
Some forms of destructuring + defualting
basically anything with widening / freshness (including Symbol, unfortunately)
class expressions
Isolated declarations is designed to be syntax-only, meaning an external implementation (or TS internally) must always be able to detect when there's a problem or produce an equivalent annotation / initializer.
If we do want to allow these things, then dts emit is going to have to gain some sort of syntax or builin type to describe these behaviors, but right now, they don't really exist.
While visually will take some getting used to, I suppose that's a good enough solution (thank you for taking the time to think of and provide one and not just mansplaining how things work).
thank you for providing one and not just mansplaining how things work
"Mansplaining" assumes bad faith; it isn't meant to be patronizing. Generally it's been my experience that when you tell people there's a design limitation preventing a desired behavior, they tend to say "well why can't you just do/not do this one thing instead", so it's easier just to explain how things interconnect upfront.
Activity
jakebailey commentedon May 2, 2024
My impression was that
satisfiesmay impact the contextual type of an expression and cause its type to change, such that its type may not be syntactically inferable. (Need to dig up that example again, though.)MichaelMitchell-at commentedon May 2, 2024
Yep I've definitely seen cases where
satisfiesinfluences the contextual type of an expression, but I wonder if theas const+ direct assignment to a variable is a sufficiently well-defined scenario that we can always trivially extract the type.dragomirtitian commentedon May 2, 2024
It is not unfortunately:
Playground Link
MichaelMitchell-at commentedon May 2, 2024
I wonder if the problem boils down to it not being possible to determine whether the
constinference of an expression or thesatisfiesinference or combination of the two leads to the more specific type, then can we defer that decision down the line, so thatwould be emitted as something like
Are there cases where knowing only the
constinference of an expression + thesatisfiestype constraint isn't sufficient to determine the contextually inferred type?MichaelMitchell-at commentedon May 2, 2024
Forgive me for pushing on this, as I'm sure folks are eager to treat this as an open and shut case. We have hundreds of instances of this pattern in our code base, the majority in which are cases where
satisfieswouldn't affect the contextually inferred type. We adopted the operator early on under a different assumptionSo while we could migrate back to our old pattern (since duplicating the structure of the expression with an explicit type is the less desirable option) of doing a type test like
asking developers to write unidiomatic code with an abstruse explanation is an outcome I want to push against.
[0] https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/#satisfies
fatcerberus commentedon May 2, 2024
satisfiesinvoking contextual typing is a necessary evil imo; you want e.g.[42] satisfies [number]to succeed, but for that you need to contextually type[42]by[number]so that it doesn't widen to an array type before it can be checked. But that in turn means that[42]ultimately gets inferred as a tuple type instead of an array type. There's no mechanism to "reverse" that after-the-fact because it actually changes which type is initially inferred for the expression.MichaelMitchell-at commentedon May 2, 2024
Bruce Pascoe (@fatcerberus) I get that, I'm not looking for a rationalization of the behavior
jakebailey commentedon May 2, 2024
There's a general class of "operations that non-trivially affect the actual type", including but not limited to:
satisfies... ? ... : ...Isolated declarations is designed to be syntax-only, meaning an external implementation (or TS internally) must always be able to detect when there's a problem or produce an equivalent annotation / initializer.
If we do want to allow these things, then dts emit is going to have to gain some sort of syntax or builin type to describe these behaviors, but right now, they don't really exist.
RyanCavanaugh commentedon May 2, 2024
If the
satisfiesoperator doesn't change the type of the inferred expression, then it's always safe to rewrite this into two lines:MichaelMitchell-at commentedon May 2, 2024
While visually will take some getting used to, I suppose that's a good enough solution (thank you for taking the time to think of and provide one and not just mansplaining how things work).
fatcerberus commentedon May 2, 2024
"Mansplaining" assumes bad faith; it isn't meant to be patronizing. Generally it's been my experience that when you tell people there's a design limitation preventing a desired behavior, they tend to say "well why can't you just do/not do this one thing instead", so it's easier just to explain how things interconnect upfront.
Also why is "mansplaining" even a word