TypeScript: Allow setter type to be incompatible with the getter type
Suggestion
đ Search Terms
differing accessor types
â Viability Checklist
My suggestion meets these guidelines:
- This wouldnât be a breaking change in existing TypeScript/JavaScript code
- This wouldnât change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isnât a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScriptâs Design Goals.
â Suggestion
#42425 forces the getter type to be assignable to the setter type. This makes the feature limited on the following DOM typing case, and thus it could be great if the limitation can be lifted.
đ Motivating Example
[Exposed=Window]
interface CSSStyleRule : CSSRule {
attribute CSSOMString selectorText;
[SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style;
};
interface CSSStyleRule extends CSSRule {
selectorText: string;
get style(): CSSStyleDeclaration;
set style(cssText: string); // currently an error
}
document.body.style = "display: none" // thus still an error while the actual behavior allows it đ€
đ» Use Cases
Allows Web IDL readonly attributes to be assignable, and thus the DOM typing better matches the actual behavior.
Transferred from https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/996.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 54
- Comments: 22 (5 by maintainers)
Commits related to this issue
- refactor(common): code cleaning * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microsoft/typesc... — committed to JeanMeche/angular by JeanMeche 2 years ago
- refactor(common): code cleaning * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microsoft/typesc... — committed to JeanMeche/angular by JeanMeche 2 years ago
- refactor(common): code cleaning * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microsoft/typesc... — committed to JeanMeche/angular by JeanMeche 2 years ago
- refactor(common): code cleaning * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microsoft/typesc... — committed to JeanMeche/angular by JeanMeche 2 years ago
- refactor(common): code cleaning * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microsoft/typesc... — committed to JeanMeche/angular by JeanMeche 2 years ago
- refactor(common): code cleaning * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microsoft/typesc... — committed to JeanMeche/angular by JeanMeche 2 years ago
- refactor(common): code cleaning (#48476) * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microso... — committed to angular/angular by JeanMeche 2 years ago
- refactor(common): code cleaning (#48476) * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microso... — committed to angular/angular by JeanMeche 2 years ago
- refactor(common): code cleaning (#48476) * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microso... — committed to angular/angular by JeanMeche 2 years ago
- refactor(common): code cleaning (#48476) * removing guard as console.warn is now widely supported * Couldn't remove non-null assertion, waiting for TS support of getters with different types (microso... — committed to trekladyone/angular by JeanMeche 2 years ago
Hi yâall, Iâd like +1 this proposal as well. In Relay (relay.dev), we are working on a feature where graphql linked fields can be updated with simple assignment, instead of the ugly existing API
recordProxy.setLinkedRecord(...)
. A simplified example would be:This allows us to enforce that any user that can be assigned to
best_friend
must have had theAssignableBestFriend_user
fragment spread at that location. Essentially, using this mechanism, we are letting the Relay compiler validate assignments. However, we donât want to enforce that any field that is assigned tobest_friend
must also have aname
selection, or to include the$fragmentRefs
field from the getter.(This is only part of what is required to ensure that the assignment is valid, but the rest is irrelevant for the getter/setter discussion.)
Thank you! It would be a pity to be able to roll this out with full type safety for users of Flow, but to have limited type safety in Typescript.
I actually brought this up a few weeks ago and we agreed itâs worth some experimenting during 5.1. I just forgot to update the issue afterwards; thanks for the reminder.
To be fair though, #2521 is closed because #42425 was thought to address it. This issue was raised afterwards to present use cases that #42425 did not address.
+1 for this feature. Flagging this issue that contains lots of great use cases for incompatible getter/setter types: https://github.com/microsoft/TypeScript/issues/2521
Lending my support to this proposal. Thankfully language ability trumps subjective opinion. If we wanted to write a bunch of
getThing
andsetThing
methods, weâd probably be in Java.Thank you!
A periodic reminder to the TS staff that the community has been asking for this since 2015 (#2521).
Why not just make a GetâŠ() and SetâŠ() function? Getters and setters are supposed to be so simple that they are similar in use as fields.
Perhaps a unique use case, but Iâll log mine here. I wanted to allow providing an update function to pass to Immer in addition to just setting the new value. This works fine in JS, but I canât get the Type definitions to comply
use case:
getter/setter in mapped type for proxy value with different types for reactive (rxjs like) api
I have Proxy object, that simplifies api for rxjs like values
When I get value from this Proxy, I just read last memoized value
When I assign to this value, I should be able to assign both âupdaterâ or value type
Example code:
Type of Proxy here should be:
Not found any hacks/workarounds here, because mapping object with get/set captures only getterâs type:
Actually typescript should add âsetâ modifier for fields along with eg âreadonlyâ; Which should work same way and check assigment type:
And âgetâ modifier is just âreadonlyâ which will be resolved similar to function overloading (if âreadonlyâ and âsetâ presents for same field)
I feel like the pot holes generated by having different get/set types can also be overcome by TypeScript.
I believe most people are going to support same types and over load them to be different as well for example
string | number
extendsstring
, so even JavaScript developers who are expectingget
andset
to be the same type shouldnât have any issuesEdit: This argument is invalid. This is the default behavior.
Your code is equivalent to this:
⊠as URLSearchParams has special stringification behavior. So no, it can be used without this feature.
I mean, it will literally never do what you want or expect, unless you just want to watch the
worldDOM burn. Preventing runtime errors is kind of priority one, but preventing blatantly obvious behavioral errors is also a goal.@MaximSagan If there is no getter, then the type would be
never
meaning that it will always extend the setter type. If this issue gets âfixedâ, then it will actually hide your problem even further. As @thw0rted commented, you want a linter rule.Or you can just scream at the junior dev for not making it an idiomatic
setProperty()
functionJust wanted to flag another Web API that isnât able to be used without this feature:
The URL.search getter returns
string
, but thesetter
also accepts aURLSearchParams
object, so the following fails to compile:with
error TS2322: Type 'URLSearchParams' is not assignable to type 'string'.
, despite it being valid.That should still be a static error because itâs virtually
el.style = el.style.toString()
where the string becomes[object CSS2Properties]
.In the âRestrictionsâ section near the top of #42425, Ryan said that â
obj.x = obj.x;
must be legal assuming obj.x is writable at allâ in order to âprevent novel unsoundness from occurringâ. Smarter people than I will have to tell you exactly why thatâs so but it also seems to align with the Goals:x=x
sure seems âlikely to be an errorâAlso, in case it matters,
el.style = el.style
might not do what you want, but it does not cause a runtime error.