Skip to content

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

@TheCymaera

Description

@TheCymaera

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions