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
I'd like to propose a new feature for TypeScript that I believe would significantly enhance the language's type safety for functions that invariably have side-effects.
Type Propagation is a feature that allows functions to modify the types of their arguments, at the call site, propagating these type changes throughout the codebase. This feature is inspired by TypeScript's existing type narrowing capabilities and concepts from languages like Rust, which enforce static guarantees about resource ownership and state transitions.
Type Propagation would enable functions to modify the types of their input parameters based on specified state transitions, providing a mechanism for enforcing type safety in functions with side effects.
Syntax:
functionreadStream(stream: Stream<'unread'>): void->stream is Stream<'read'>{// Implementation herestream.state='read';}
In this example, the function readStream takes a Stream<'unread'> as input and updates its state property to 'read'. The -> stream is Stream<'read'> syntax indicates that after calling readStream, the type of the stream argument will be updated to Stream<'read'>.
Type Propagation ensures that functions with side effects accurately reflect changes in the types of their arguments. This would prevent runtime errors, for example after reading a stream that can only be read once - the code can express type transformations in function signatures, making code more explicit, self-documenting, and hopefully easier to understand.
The feature is inspired by concepts found in languages like Rust, where functions can enforce static guarantees about resource ownership and state transitions.
Note that type propagations would need to propagate through multiple layers of function calls, ensuring that type modifications are applied consistently across the codebase. (For simplicity, I'm not covering this in detail now, since the proposal is at the "idea" stage - there would be more design work involved in defining this feature, including things like async/await, generics, and probably other things.)
π Motivating Example
// Define a type representing a stream with a mutable state propertytypeStream<Sextends'unread'|'read'>={state: S;};// Define a function that propagates type changesfunctionreadStream(stream: Stream<'unread'>): void->stream is Stream<'read'>{stream.state='read';}// Usage exampleconstmyStream: Stream<'unread'>={state: 'unread'};// Call readStream to transition myStream to a 'read' statereadStream(myStream);// Now, myStream's type is Stream<'read'>readStream(myStream);// π error
π» Use Cases
What do you want to use this for? it could hopefully improve types of things like streams in Node and browser APIs - but it might also be useful for things like mutable state in UI libraries, type-safety in state management libraries, and so on.
What shortcomings exist with current approaches? mainly, type narrowing can't account for effects.
What workarounds are you using in the meantime? things like immutability, monads and functors might serve as workarounds, but can't account for existing APIs, or for types that are inherently mutable in nature, such as read-once streams.
The text was updated successfully, but these errors were encountered:
If this sort of feature were to happen, I would think that ideally #11498 should happen at the same time so that these stateful types aren't blocked by idiomatic code structures that are opaque to CFA.
π Search Terms
type propagation, type effects
β Viability Checklist
β Suggestion
I'd like to propose a new feature for TypeScript that I believe would significantly enhance the language's type safety for functions that invariably have side-effects.
Type Propagation is a feature that allows functions to modify the types of their arguments, at the call site, propagating these type changes throughout the codebase. This feature is inspired by TypeScript's existing type narrowing capabilities and concepts from languages like Rust, which enforce static guarantees about resource ownership and state transitions.
Type Propagation would enable functions to modify the types of their input parameters based on specified state transitions, providing a mechanism for enforcing type safety in functions with side effects.
Syntax:
In this example, the function
readStream
takes aStream<'unread'>
as input and updates itsstate
property to'read'
. The-> stream is Stream<'read'>
syntax indicates that after callingreadStream
, the type of thestream
argument will be updated toStream<'read'>
.Type Propagation ensures that functions with side effects accurately reflect changes in the types of their arguments. This would prevent runtime errors, for example after reading a stream that can only be read once - the code can express type transformations in function signatures, making code more explicit, self-documenting, and hopefully easier to understand.
The feature is inspired by concepts found in languages like Rust, where functions can enforce static guarantees about resource ownership and state transitions.
Note that type propagations would need to propagate through multiple layers of function calls, ensuring that type modifications are applied consistently across the codebase. (For simplicity, I'm not covering this in detail now, since the proposal is at the "idea" stage - there would be more design work involved in defining this feature, including things like async/await, generics, and probably other things.)
π Motivating Example
π» Use Cases
The text was updated successfully, but these errors were encountered: