add a constraint for immutable types
See original GitHub issuesay, i have a generic function that by design requires that its parameters may only take immutable arguments, i wish i could get such guarantee from TS by declaring my function as follows:
function doThings<readonly T>(value: T): Result<T> {
// ...
}
as far as how to make an interface immutable:
readonly interface Point {
readonly x: number;
readonly y: number;
}
so the problem being solve here is to make sure that the caller won’t mutate the argument after it is passed to the function
simple use case: a hash-based data container, which calculates a hash of a given value, and will store it at that hash, and it all will work until the value is mutated outside and tha stored hash is no longer valid, so the container doesn’t really work anymore
another use case: a cache or object pool or any other situation when there are many parties involved in taking hold of the same object, which must be guaranteed from being mutated by one party to prevent spooky action at a distance for all other parties
Issue Analytics
- State:
- Created 6 years ago
- Reactions:5
- Comments:7 (3 by maintainers)

Top Related StackOverflow Question
i was talking about special generic constraints that would guarantee that a type argument is immutable
what did you mean by
Readonly?i am afraing it doesn’t work at least in the latest version of TS, because anything can be used in place of
Readonly<T>parameter including interfaces with all writable propertiesI support the goals of this proposal. Some design issues:
For the interface modifier that asserts that the object is immutable, overloading the
readonlykeyword is very confusing (it looks like it already confused mhegazy). Ideally we should useimmutable, though I don’t know if there are concerns about adding new reserved words. (I’ll useimmutablein the rest of my comment.)What prevents an interface containing the same members without the
readonlymodifier from being assigned structurally to thePointinterface as declared above? Is theimmutablemodifier of a type one more thing that is checked for assignability?Users may want mutable, read-only, and immutable versions of the same interface. The current proposal for read-only (#10725 / #18770) is that the user defines a mutable interface
Pointand writesreadonly Pointfor a deep read-only version (perhaps what “deep read-only” means has to be customized in some cases). Similarly, I’d like to writeimmutable Pointfor the deep-immutable interface. In essence, theimmutableoperator should declare fields that form part of the abstract state of the object to beimmutablethemselves; these are the same fields that becomereadonlyalong with the interface. Theimmutableinterface has the same methods as thereadonlyinterface. Given such an operator, the original example could be written as:but additionally having an
immutabletype parameter constraint may be clearer for users and/or make implementation easier depending on how type argument inference works (yikes).immutableobjects? One way is always a type assertion, or adeepFreezemethod that uses reflection to find out what fields it should recursivelydeepFreezeand then asserts the result to beimmutable. We could additionally consider ways of constructing a single new immutable object from existing immutable parts, e.g.:To use the same constructor to construct both mutable and immutable objects, we need to make it polymorphic in whether the new object is mutable. I.e., we think of the presence or absence of the
immutablemodifier on the call as a generic parameter of the constructor, and throughout the constructor’s signature and body, theownedtype modifier refers to this parameter. Then the compiler checks every assignment to a field to ensure that if the new object is immutable, then the reference being assigned is immutable. (Is anyone aware of precedent for this in other programming languages? I could research it myself, but I’ve spent enough time on this already.)