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

Create ES3 specific lib.d.ts #2410

Closed
SergioMorchon opened this issue Mar 18, 2015 · 23 comments
Closed

Create ES3 specific lib.d.ts #2410

SergioMorchon opened this issue Mar 18, 2015 · 23 comments
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript VS Code Tracked There is a VS Code equivalent to this issue

Comments

@SergioMorchon
Copy link

By targeting to ES3, the following code (within a class definition):

        setOptionDisable(option: HTMLOptionElement, operation: EnumOperations) {
            ko.applyBindingsToNode(option,
                {
                    disable: BI_OP.has(operation)? this.selectedNumbers().length >= 2 : true
                }, item);
        }

compiles, but the item variable is not defined. Does really item exists in a ES3 standard browser? I wasn't able to find it, so I treated this as a bug.

@danquirk
Copy link
Member

You'll need to post more repro code. Simply using an undefined name like that in a small snippet is clearly an error. If there's actually a bug in the compiler or your code it's more involved than just that function definition.

@danquirk danquirk added the Needs More Info The issue still hasn't been fully clarified label Mar 18, 2015
@SergioMorchon
Copy link
Author

On the lib.d.ts file is defined the following function:

declare function item(index: any): any;

But as seeing @ http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf 15.1.1 Value Properties of the Global Object (page 77) and W3C http://www.w3schools.com/jsref/jsref_obj_global.asp , there isn't any item global function.

This misstake causes that if I use a non-defined ítem variable on my code, which of course doesn't exists, it will compile ok, but it shouldn't!

For example:

item();// must throw a compilation error. Instead, it is getting a runtime one on the browser because  it is not defined.

Same with msClearImmediate, btoa, atob, etc.

I think I can't explain it better... :S

@SergioMorchon SergioMorchon changed the title ES3 "item" global function in lib.d.ts ES3 non-ES3 global function in lib.d.ts Mar 20, 2015
@danquirk
Copy link
Member

Ah, we could consider an ES3 specific lib.d.ts. In the meantime you should just remove those members from the copy of lib.d.ts you're building against or polyfill the implementation if you're targeting both ES3 and ES5 and want that functionality everywhere. We already see most people targeting ES5+ and that's only going to increase so this isn't likely to be super high priority to fix right now.

@danquirk danquirk added Suggestion An idea for TypeScript and removed Needs More Info The issue still hasn't been fully clarified labels Mar 20, 2015
@danquirk danquirk changed the title ES3 non-ES3 global function in lib.d.ts Create ES3 specific lib.d.ts Mar 20, 2015
@RyanCavanaugh
Copy link
Member

Would probably accept a PR on a good es3.lib.d.ts

@SergioMorchon
Copy link
Author

This is very interesting at Enterprise environments that works with legacy browsers.

@mhegazy mhegazy added the Help Wanted You can do this label Dec 9, 2015
@mhegazy
Copy link
Contributor

mhegazy commented Feb 22, 2016

related to #6974

@ericdrobinson
Copy link

I understand that this is a relatively old Issue, but I would like to toss in a use-case for providing an es3-specific declaration lib. I find myself working with the [admittedly aging] ExtendScript language, one that is primarily used for creating extensions to Adobe products. The language itself is ECMAScript 3-based.

It appears to be possible to write TypeScript such that compiled JavaScript can work with this language:

  • Specify the "es5" lib in the compiler options (or whatever you wish to write in).
    • Omit the "dom" lib.
  • Set the target compiler option to "es3".
  • Provide declaration files for other ExtendScript types.

However, it is not possible to write type-annotated ExtendScript in a TypeScript enabled environment. With a lib.es3.d.ts declaration file option, this would be possible with very little change to the above configuration:

  • Specify the "es3" lib in the compiler options. [<-- Missing!]
  • Provide declaration files for other ExtendScript types.

As it stands, we can get most of the way by specifying "es5". The obvious pitfall with this strategy is that some features/APIs suggested with type completion will be erroneous/not supported by the target language.

Would be nice to have an "es3" lib option...

@mhegazy
Copy link
Contributor

mhegazy commented Apr 28, 2017

Would be nice to have an "es3" lib option...

it sure would be. and this issue is tracking it. we would be happy to accept a PR for lib.es3.d.ts

@ericdrobinson
Copy link

Speaking for myself, I have no clue as to how the existing lib declaration files were built. Suggestions on how to quickly create a lib.es3.d.ts file (perhaps by modifying the existing es5 version?) would be instructive. Furthermore, what would you suggest to use for the target spec? This? If so, what portions are most important? I would guess that Chapter 15 - Native ECMAScript Objects would be the primary focus. Are there any other important sections? Anything important to capture in Chapter 8 - Types or Chapter 9 - Type Conversion? Or are those things handled intrinsically by TypeScript already?

@mhegazy
Copy link
Contributor

mhegazy commented May 1, 2017

I would start by lib.es5.d.ts, and go through he spec remove/update declarations as necessary.

@ericdrobinson
Copy link

Out of curiosity, does lib.es5.d.ts correspond to version 5.0 or 5.1?

@mhegazy
Copy link
Contributor

mhegazy commented May 1, 2017

5.1

@ericdrobinson
Copy link

@mhegazy Is there a resource that describes how the lib files are structured and why they are structured in the manner that they are? For example, why are all built-in types declared as interfaces with equivalently named global constants rather than classes?

This seems to make some kind of sense for static-like classes (e.g. Math). However, what about the basic Object class? Why split it up into an Object interface and an ObjectConstructor interface? It looks like this is . There doesn't appear to be a good description for this at the top of the lib file itself, nor in the declaration file documentation. Some googling led me to "construct signatures", which is somewhat covered in the "Difference between the static and instance sides of classes" section of the TypeScript Interface documentation. What's somewhat confusing is that TypeScript classes can have static methods/fields. So why not just use those?

One drawback(?) that I'm seeing with the interface method being employed is that [when using JavaScript, at least] the global namespace is filled not with classes as one might expect, but interfaces. I understand that JavaScript classes are not "real" classes, per se, but it is also somewhat surprising to see autocomplete turn up ObjectConstructor as a valid completion target.

Basically, why this:

// Instance-side.
interface Blah {
    num: number;
}

// Static-side.
interface BlahConstructor {
    val: object;
    new (): Blah;
}

declare const Blah: BlahConstructor;

instead of this:

declare class Blah {
    constructor();
    static val: object;
    num: number;
}

Convention? Or some deeper reason...?

(Please let me know if there is a better place to ask such questions. I ask them here to help anyone else considering taking on the task of creating the "es5" lib who may also not be terribly familiar with "why" behind the architecture.)

@mhegazy
Copy link
Contributor

mhegazy commented May 1, 2017

@mhegazy Is there a resource that describes how the lib files are structured and why they are structured in the manner that they are? For example, why are all built-in types declared as interfaces with equivalently named global constants rather than classes?

classes are not callable. most of the built-in objects e.g. Object, Array, etc.. allow to be called as function as well as a constructor.

@mhegazy
Copy link
Contributor

mhegazy commented May 1, 2017

One drawback(?) that I'm seeing with the interface method being employed is that [when using JavaScript, at least] the global namespace is filled not with classes as one might expect, but interfaces. I understand that JavaScript classes are not "real" classes, per se, but it is also somewhat surprising to see autocomplete turn up ObjectConstructor as a valid completion target.

that is unfortunate, and we tried to limit it to only required objects, e.g. DOM APIs do not behave the same way.

One thing to note, you need to keep the structure, for things like ObjectConstructor, the assumption when ppl use --lib es3 is that they will get a smaller API surface area, not a completely different one.

@ericdrobinson
Copy link

ericdrobinson commented May 2, 2017

On Callable Core "classes"

classes are not callable. most of the built-in objects e.g. Object, Array, etc.. allow to be called as function as well as a constructor.

Ahh, so that is what the last two lines of this are then:

interface ObjectConstructor {
    new (value?: any): Object;
    (): any;
    (value: any): any;
    //...
}

I'd actually not previously understood why those were there. Makes much more sense.

Improvements to Callable Object() Declarations?

I cross checked those with the spec. It seems to me that the two lines listed above may not be quite as accurate as they could be. I would E.g.:

interface ObjectConstructor {
    // Construct Signature (as exists now):
    new (value?: any): Object;

    // These "return a new Object object" (https://www.ecma-international.org/ecma-262/5.1/index.html#sec-15.2.1.1):
    (): Object;
    (value: undefined): Object;
    (value: null): Object;

    // These are outlined in Table 14 (https://www.ecma-international.org/ecma-262/5.1/index.html#sec-9.9):
    (value: boolean): Boolean;
    (value: number): Number;
    (value: string): String;
    <T>(value: T): T;    // "The result is the input argument (no conversion)."

    //...
}

Or am I missing something here? Quick tests in the browser's JavaScript console seem to confirm that this works. Further, with the above additions, VisualStudio Code will correctly determine the type of the output based on the input.

Un-implementable Interfaces?

Also, is the idea with the "callable interfaces" that they will simply make the interface un-implementable? I attempted to implement ObjectConstructor in a test class and got the following error:

'Class 'test' incorrectly implements interface 'ObjectConstructor'.
  Type 'test' provides no match for the signature '(): any''

I take it that this is "by design"?

Maintaining the Current Structure with an es3 Variant

One thing to note, you need to keep the structure, for things like ObjectConstructor, the assumption when ppl use --lib es3 is that they will get a smaller API surface area, not a completely different one.

Agreed. This was part of the impetus for requesting more information as to the structure of the declarations. Understanding why the structure is as it is will help anyone attempting to create a lib.es3.d.ts file.

@ericdrobinson
Copy link

Also, is the idea with the "callable interfaces" that they will simply make the interface un-implementable?
...
I take it that this is "by design"?

I'll answer my own question here. Yes: it appears that this is by design.

For anyone interested in more, this blog entry is extremely helpful. The main documentation is also helpful if you look for "call signature" (under Function Types) and "construct signature" (under Difference between the static and instance sides of classes).

@mhegazy
Copy link
Contributor

mhegazy commented May 4, 2017

I cross checked those with the spec. It seems to me that the two lines listed above may not be quite as accurate as they could be. I would E.g.:

sure. it just that ppl do not use Object(1) that often.

@mhegazy
Copy link
Contributor

mhegazy commented May 4, 2017

I take it that this is "by design"?

yes. these are not meant to be implemented, but rather to describe JS objects that do exist.

@ericdrobinson
Copy link

ericdrobinson commented May 4, 2017

sure. it just that ppl do not use Object(1) that often.

@mhegazy I bet. Doesn't mean that it isn't technically wrong ;)

@mhegazy
Copy link
Contributor

mhegazy commented May 4, 2017

@mhegazy I bet. Doesn't mean that it isn't technically wrong ;)

it is not wrong. it is just not that common.

This was referenced May 20, 2017
@saschanaz
Copy link
Contributor

Reopened my PR as #28372, if anyone still is interested.

@RyanCavanaugh RyanCavanaugh modified the milestones: Community, Backlog Mar 7, 2019
@RyanCavanaugh RyanCavanaugh added Declined The issue was declined as something which matches the TypeScript vision and removed Help Wanted You can do this labels Aug 21, 2019
@RyanCavanaugh RyanCavanaugh removed this from the Backlog milestone Aug 21, 2019
@RyanCavanaugh
Copy link
Member

Comments in the linked PR

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 VS Code Tracked There is a VS Code equivalent to this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants