Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Type Propagation #57424

Closed
6 tasks done
mindplay-dk opened this issue Feb 16, 2024 · 3 comments
Closed
6 tasks done

Feature: Type Propagation #57424

mindplay-dk opened this issue Feb 16, 2024 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@mindplay-dk
Copy link

πŸ” 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:

function readStream(stream: Stream<'unread'>): void -> stream is Stream<'read'> {
  // Implementation here
  stream.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 property
type Stream<S extends 'unread' | 'read'> = {
  state: S;
};

// Define a function that propagates type changes
function readStream(stream: Stream<'unread'>): void -> stream is Stream<'read'> {
  stream.state = 'read';
}

// Usage example
const myStream: Stream<'unread'> = { state: 'unread' };

// Call readStream to transition myStream to a 'read' state
readStream(myStream);

// Now, myStream's type is Stream<'read'>
readStream(myStream); // πŸ‘ˆ error

πŸ’» Use Cases

  1. 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.
  2. What shortcomings exist with current approaches? mainly, type narrowing can't account for effects.
  3. 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.
@Andarist
Copy link
Contributor

Duplicate of #41339

@snarbies
Copy link

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.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Feb 16, 2024
@typescript-bot
Copy link
Collaborator

This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Feb 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants