Description
f# Readonly on Exports from Namespaces (#16720)
namespace N {
export class C { }
}
N.C = class {};
- Namespaces have had this feature for a while now
- Breaking changes for something that's functioned that way this long seems strange.
- Declined
Readonly & Variance
-
One thing that comes up quite a bit is strict variance.
-
If we enabled stricter variance, that would imply that
Array
becomes invariant.- To get a covariant array, you need a
ReadonlyArray
. - This means everything gets two declarations -
T
andReadonlyT
- To get a covariant array, you need a
-
Strict variance is easy to enable, but would be hard to make easy to use.
-
This leads us to start thinking about how to quickly make a readonly version of a type.
-
We've had an experimental type operator called
readonly
- Much like
keyof T
, you just writereadonly T
.
- Much like
-
Like the
Readonly
mapped type, it makes all propertiesreadonly
as well.- However, the
Readonly<T>
mapped type doesn't eliminate mutating methods at all.
- However, the
-
This means we needed to add a way to indicate that a method doesn't mutate its object.
- Created the
this: readonly
syntax.
- Created the
-
Example:
class Foo { name: string; getName(this: readonly): string; setName(value: string): void; } // This: type ReadonlyFoo = readonly Foo; // ... is equivalent to this: type ReadonlyFoo = { readonly name: string; readonly getName(this: readonly): string; }
-
What about deep readonly?
- In other words, does
readonly Foo[]
give you areadonly Array<readonly Foo>
? - Have thus far decided no.
- Could create an
immutable
type operator- Q: Couldn't you implement that with mapped types?
- A: Potentially
- May be a bit confusing since state could be captured outside of current object
- Q: Couldn't you implement that with mapped types?
- Could create an
- In other words, does
-
In
--strictReadonly
mode, thisreadonly
operator would work as described above.readonly T
not assignable toT
.readonly
props would not be assignable to mutable props.readonly T
removes mutating methods
-
Outside of
strictReadonly
,readonly T
is justReadonly<T>
-
All of this means that library authors would need to enable readonly mode.
-
Would TypeScript be able to infer whether a method is readonly or not?
- Kind of tricky, methods transitively call each other.
-
How bad are strict variance modes without this?
- Special hell for passing callbacks.
- Need a
super
constraint for generics - otherwise many types stay invariant by virtue of taking aT
as an input position.
-
Will people know how to use
this: readonly
?- Seems like people will always need to be mindful of this when they write
.d.ts
files. - How will we generate this for the DOM if the metadata isn't present? What about
readonly HTMLElement
?
- Seems like people will always need to be mindful of this when they write
-
How do
this: readonly
parameters work with overloads?- Currently, if any overloads are not declared with
this: readonly
, the property is eliminated. - That's not going to play well with libraries.
- Example: Knockout.
- Currently, if any overloads are not declared with