Skip to content

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

Closed

Description

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:

Activity

  1. RyanCavanaugh commented on Mar 26, 2019

    @RyanCavanaugh
    Member

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

  2. bluelovers commented on Mar 27, 2019

    @bluelovers
    ContributorAuthor

    Ryan Cavanaugh (@RyanCavanaugh) anything is like this or replace this?

  3. trusktr commented on Nov 17, 2019

    @trusktr
    Contributor

    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?

  4. trusktr commented on Nov 17, 2019

    @trusktr
    Contributor

    anything is like this or replace this?

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

  5. mike-marcacci commented on Apr 16, 2020

    @mike-marcacci

    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.

  6. mike-marcacci commented on Apr 16, 2020

    @mike-marcacci

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    DeclinedThe issue was declined as something which matches the TypeScript visionSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions