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

Declare properties with a separate public and private types. #51597

Closed
5 tasks done
TheCymaera opened this issue Nov 19, 2022 · 4 comments
Closed
5 tasks done

Declare properties with a separate public and private types. #51597

TheCymaera opened this issue Nov 19, 2022 · 4 comments

Comments

@TheCymaera
Copy link

TheCymaera commented Nov 19, 2022

Suggestion

πŸ” Search Terms

Separate public and private type
Privately typed properties
Public and private types
Supertype properties
Subtype properties

βœ… 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

Let classes declare properties with separate public and private types.

πŸ“ƒ Motivating Example

class Stack<T> {
    // privately, the property is mutable
    private data: T[] = [];
    
    // publicly, the property is immutable.
    public readonly data: readonly T[];
    
    push(item: T) {
        // private type is mutable
        this.data.push(item);
    }
}

stack.data.push("foo") // Not allowed; public type is immutable

Current alternatives are verbose and/or have limitations:

Type assertion:

class Stack<T> {
    public readonly data: readonly T[];
    push(item: T) {
        (this.data as T[]).push(item);
    }

    // manually asset type every time inside class body
}

Multiple properties:

class Stack<T> {
    readonly #data: T[] = []; // cannot be re-assigned
    readonly data = this.#data as readonly T[];

    // use private property #data inside class body
}

Accessors:

class Stack<T> {
    #data: T[] = [];
    get data() {
        return this.#data as readonly T[];
    }

    // use private property #data inside class body
}

πŸ’» Use Cases

Prevent re-assignment from outside the class body.
Export a live array/set/map but prevent mutation from outside the class body.
Export superclass properties but use subclass-methods internally.

@MartinJohns
Copy link
Contributor

Duplicate of #37487.

@TheCymaera
Copy link
Author

Duplicate of #37487.

There are similar use cases but this is not a duplicate.

That suggestion does not permit using subtypes, such as making the array immutable like in my example.

@MartinJohns
Copy link
Contributor

It's in the comments.

@TheCymaera
Copy link
Author

It's in the comments.

Ah, I see.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants