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

TS2339: Property '__proto__' does not exist on type 'typeof A1'. #30587

Closed
bluelovers opened this issue Mar 25, 2019 · 6 comments
Closed

TS2339: Property '__proto__' does not exist on type 'typeof A1'. #30587

bluelovers opened this issue Mar 25, 2019 · 6 comments
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript

Comments

@bluelovers
Copy link
Contributor

bluelovers commented Mar 25, 2019

TypeScript Version: 3.4.0-dev.201xxxxx

Search Terms:

Code

maybe this should call as Feature request

import util = require('util')

export class P
{
	fn1(v: string)
	{
		return 1
	}

	static create()
	{
		console.log('P', util.inspect(this));

		console.log('this.prototype.fn1', this.prototype.fn1);
		// @ts-ignore
		console.log('this.prototype.fn2', this.prototype.fn2);

		// here has more code

		return new this
	}
}

export class A1 extends P
{
	fn1(v: string | number)
	{
		return 1
	}

	fn2(v: string | number)
	{
		return 1
	}

	static create(): A1
	{
		// TS2339: Property '__proto__' does not exist on type 'typeof A1'.
		let superStatic = this.__proto__;

		console.dir(superStatic);
		console.dir(superStatic.create);

		return superStatic.create.call(this)
	}
}

console.log(A1.create().fn2(1));

Expected behavior:

no error, and typescript know superStatic is typeof P


Feature request here

hope can have something like

static create(): ThisType<this>

make without always write

static create(): XXX

or a way to get P from A1 , when we didn't know who is A1 parent class in static

Actual behavior:

TS2339: Property '__proto__' does not exist on type 'typeof A1'.

Playground Link:

Related Issues:

@RyanCavanaugh RyanCavanaugh added Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript labels Mar 26, 2019
@RyanCavanaugh
Copy link
Member

We're not adding new support for discouraged constructs like __proto__

@bluelovers
Copy link
Contributor Author

@RyanCavanaugh anything is like this or replace this?

@trusktr
Copy link
Contributor

trusktr commented Nov 17, 2019

discouraged constructs like proto

Now that it is officially spec'd in the ES spec, why not support it?

My experience is that it does behave exactly the same in all major browsers and Node.

Are there inconsistencies in modern engines? Old engines don't even have Object.set/getPrototypeOf anyways, if people are trying to target those.

Many people use __proto__ because it is nice!

I much prefer the obj.__proto__/obj.__proto__ = {} syntax over Object.getProtypeOf(obj)/Object.setProtypeOf(obj, {}). Plus, declarative syntax, like:

let o = {
  __proto__: otherObject,
  foo: 123,
}

and how well it combines with spread syntax or with Object.assign. The get/setPrototypeOf methods are not just as flexible.

A special case in TS can be made so that __proto__ can not be configured, if that safety is desired by TS team. I'm not sure how, but can't a call to Object.defineProperty(..., '__proto__') be made into a type error?

@trusktr
Copy link
Contributor

trusktr commented Nov 17, 2019

anything is like this or replace this?

@bluelovers Object.getProtypeOf(obj)/Object.setProtypeOf(obj, {})

@mike-marcacci
Copy link

mike-marcacci commented Apr 16, 2020

This relates to #37963 (which IMO is a pretty serious correctness/security issue) in that these are equivalent:

const safeStringMap: { [key: string]: string } = Object.create(null);
const safeStringMap: { [key: string]: string } = { __proto__: null };

I believe that typescript needs to support __proto__ in object literals only. The rationale here is that once #37963 is fixed, the following will (correctly) fail, because keys constructor, hasOwnProperty, __proto__, etc are NOT strings but are accessible properties:

const safeStringMap: { [key: string]: string } = {
  ...someOtherStringMap
};

Adding support for __proto__ inside object literal definitions allows us to fix this by writing:

const safeStringMap: { [key: string]: string } = {
  __proto__: null,
  ...someOtherStringMap
};

Otherwise, writing safe indexed objects requires us to avoid spreads entirely:

const safeStringMap: { [key: string]: string } = Object.assign(
  Object.create(null),
  someOtherStringMap
);

Also, this may be a duplicate of #13933 (or vice-versa).


EDIT: I have turned this into a more thoroughly constructed proposal in #38385.

@mike-marcacci
Copy link

mike-marcacci commented Apr 16, 2020

I've avoided creating a new issue for my specific suggestion, since these two are already open... but I do see that this one is marked as "declined": if it would be preferable to have a new specific issue to talk about supporting this only in object literals, let me know and I'll create one.

This proposal has been submitted as #38385.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants