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

private fields in nested classes should have separate types? #60882

Open
6 tasks done
trusktr opened this issue Dec 30, 2024 · 3 comments
Open
6 tasks done

private fields in nested classes should have separate types? #60882

trusktr opened this issue Dec 30, 2024 · 3 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@trusktr
Copy link
Contributor

trusktr commented Dec 30, 2024

πŸ” Search Terms

typescript private field nested class

βœ… Viability Checklist

⭐ Suggestion

Private fields of a wrapper class are similar to symbols: perhaps the nested classes could have their own types for the fields based on the value they initialize in their constructor:

πŸ“ƒ Motivating Example

https://www.typescriptlang.org/play/?noImplicitAny=false#code/MYGwhgzhAEBiBOBLApgOwCYwN4CgCQAxAG5ggCuyO+sA9jdALzSiQy33IAeALmpnEj7Z8eYDVQRu8MsG414ACgCU0XHnUQyAB2SKlIvNwAWiCADpipCo2gAWAKwA2aAHoX0ADwBaH779foVDIAWwAjXREAXyp1ADM6AFlkYxp0ZVUDMQkaEGQzEBoAcwVjUwsScmR9dWi8aPwAITB4GxYoaCaWrl4MGFLzdgz1LMlpWXl0tQ1tXWUDfvKrZBsAIgB2AA4AThXXd29-Q59oUcRUQqiYvFDmpJS0lSnRcQgcvILihctK6rr8aPqI24qnYABoOs1IjZUMgAO4CFC9OY4IHQWLQuFwOhzVGhDHwzrI2JmeI0O5GVLpNzQD4wFYORwrHChMw3eDkykqam06DrbYrIA

Plain JS:

class Friends {
	#priv

	Foo = class Foo extends Friends {
		constructor() {
			super()
			this.#priv = 456 // <----------- number
		}

		fooMethod() {
			console.log(this.#priv)
		}
	}

	Bar = class Bar extends this.Foo {
		constructor() {
			super()
			this.#priv = "789" // <-------------- string
		}

		barMethod() {
			console.log(this.#priv)
		}
	}
}

const {Foo, Bar} = new Friends()

const f = new Foo()
const b = new Bar()

f.fooMethod() // logs "456"
b.barMethod() // logs "789"

πŸ’» Use Cases

Allows having a "private" key to use on multiple classes, but each class could have a different type of value.

@Andarist
Copy link
Contributor

I assume you might be looking for some improvements for .js files where some props can be inferred from their assignments in constructors etc.

This repro shows multiple problems (I found 2 issues in emitted .d.ts πŸ˜… ). But even this doesn't behave correctly:

// @filename: index..ts

class Friends {
  #priv;

  Foo = class Foo extends Friends {
    constructor() {
      super();
      this.#priv = 456; // missing error
      this.nonDeclared = "foo"; // errors
    }
  };
}

@Andarist
Copy link
Contributor

Actually, this works as expected. At runtime this.#priv can be accessed by subclasses when they are defined within their superclass:

class Test1 {
  #priv = 10;

  Foo = class Foo extends Test1 {
    constructor() {
      super();
      console.log(this.#priv);
    }
  };
}

const t1 = new Test1();
new t1.Foo(); // logs: 10

So as long as you don't redefine them in those subclasses (to "shadow" those private props) their type will stay the same as the one defined at the declaration site (that's an implicit any in your example).

@Andarist
Copy link
Contributor

That said, unfortunately redefining them in those nested subclasses won't be too portable. See #60885 and the reasoning outlined in the PR's description there.

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature labels Jan 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants