question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow class inheritance in ambient contexts, even with a base private constructor

See original GitHub issue

TypeScript Version: nightly (2.5.0-dev.20170902)

Code

declare namespace Foo {
    class Bar {
        private constructor();
        Box: string;
    }
    class Baz extends Bar {
        private constructor();
    }
    function generator(): Baz;
}

let x = Foo.generator();
x.Box = 'abcd';

Expected behavior: Compile without error.

Actual behavior: error TS2675: Cannot extend a class ‘Foo.Bar’. Class constructor is marked as private.

Use case This would allow declaring the types of host-supplied objects, with the following features:

  1. can inherit members from each other
  2. cannot be inherited from using standard Typescript/Javascript classes
  3. cannot be assigned to from an object literal with matching members
  4. cannot be constructed, only returned from a factory method
declare namespace com.sun.star.text {
    class XTextTablesSupplier {
        private constructor();
        private typekey: XTextTablesSupplier;
        readonly TextTables: any;
    }
    class GenericTextDocument extends XTextTablesSupplier {
        private constructor();
        private typekey1: GenericTextDocument;
        CharacterCount: number;
    }
}
declare function createInstance(typename: 'com.sun.star.text.GenericTextDocument'): com.sun.star.text.GenericTextDocument;

let x = createInstance('com.sun.star.text.GenericTextDocument'); // OK

x = new com.sun.star.text.GenericTextDocument(); // Error

let y = x.TextTables; // OK

// The following would be an error
x = {
    TextTables: '',
    CharacterCount: 5
};

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:2
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
zspitzcommented, Sep 8, 2017

@aluanhaddad The use case here is when the Javascript host supplies objects that look and behave like Javascript objects WRT reading/writing properties and calling methods, but not WRT object construction via new. Presumably instanceof would always return false at runtime, because there is no real prototype chain.

At runtime, there isn’t an actual Javascript constructor function; the underlying object is constructed via whatever mechanisms are available to the language used to develop the host (in the case of the LibreOffice API, this is either C++ or Java). private constructor is appropriate here, because the actual constructor is unavailable to any Javascript code.

why not expose it as an interface or type alias?

Because that would allow using a plain Javascript object with the appropriate members when the type is expected. If the API expects a binary C++ created object of type com.sun.star.text.GenericTextDocument, passing in a Javascript object will fail. In other words, if GenericTextDocument is declared as a class:

declare class GenericTextDocument {
    private typekey: GenericTextDocument;
}

then this can be prevented:

let x: GenericTextDocument = {
    TextTables: '',
    CharacterCount: 5
};

which is not the case if GenericTextDocument is declared as an interface or type alias.

Read more comments on GitHub >

github_iconTop Results From Across the Web

c++ - Access to own private constructors via derived class ...
A constructor so declared [as an inheriting constructor] has the same access as the corresponding constructor in [the base class] X. And in...
Read more >
TypeScript - Understanding TypeScript | Microsoft Learn
There's no way to prevent some members from not being inherited. A derived class inherits all members of the base class, including public...
Read more >
super - JavaScript - MDN Web Docs - Mozilla
The super keyword is used to access properties on an object literal or class's [[Prototype]], or invoke a superclass's constructor.
Read more >
Advanced Scenarios — Simple Injector 5 documentation
It even works for types that implement multiple closed versions of the given ... in multiple class constructors (or accessed from the container...
Read more >
Overview - TypeScript
get and set Accessors Are Allowed in Ambient Contexts ... class Box<T> { kind: "box"; value: T; constructor(value: T) { this.value = value;...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found