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

Working with ES6 Sets in Typescript #3069

Closed
robianmcd opened this issue May 7, 2015 · 15 comments
Closed

Working with ES6 Sets in Typescript #3069

robianmcd opened this issue May 7, 2015 · 15 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@robianmcd
Copy link

robianmcd commented May 7, 2015

The constructor for an ES6 Set takes an optional iterable parameter (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) but the declaration in lib.d.ts doesn't include it

declare var Set: {
    new <T>(): Set<T>;
}

So I'm getting a Typescript error if I try to do something like new Set([1,2,3]).

On a somewhat related note I'm using the 1.5 Beta version of typescript which supports a lot of ES6 features but it still relies on the browser to support Sets. Are there plans polyfill Sets in Typescript?

@mhegazy
Copy link
Contributor

mhegazy commented May 7, 2015

TypeScript does not come with built in pollyfills. it is up to you to decide which pollyfill to use, if any. you can use something like es6Collection, es6-shims, corejs..etc.
All the Typescript compiler needs is a declaration for the ES6 constructs you want to use. you can find them all in this lib file.

here is the relevant portion:

interface Set<T> {
    add(value: T): Set<T>;
    clear(): void;
    delete(value: T): boolean;
    entries(): IterableIterator<[T, T]>;
    forEach(callbackfn: (value: T, index: T, set: Set<T>) => void, thisArg?: any): void;
    has(value: T): boolean;
    keys(): IterableIterator<T>;
    size: number;
    values(): IterableIterator<T>;
    [Symbol.iterator]():IterableIterator<T>;
    [Symbol.toStringTag]: string;
}

interface SetConstructor {
    new <T>(): Set<T>;
    new <T>(iterable: Iterable<T>): Set<T>;
    prototype: Set<any>;
}
declare var Set: SetConstructor;

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label May 7, 2015
@robianmcd
Copy link
Author

How do I tell the TypeScript compiler to use lib.es6.d.ts instead of lib.d.ts? I can't just redeclare Set or I will get a Subsequent variable declarations must have the same type. error. I'm using gulp Traceur and I'm not explicitly including lib.d.ts anywhere so I'm not sure how to replace it.

@mhegazy
Copy link
Contributor

mhegazy commented May 7, 2015

You can declare it in one of your source files and you should not get the duplicate definition errors.

You can also include this file in your project and explicitly reference it..

@robianmcd
Copy link
Author

If I add something like

interface SetConstructor {
    new <T>(): Set<T>;
    new <T>(iterable: any): Set<T>;
    prototype: Set<any>;
}
declare var Set: SetConstructor;

to one of my .d.ts or .ts files I get a Subsequent variable declarations... error.

If I include a reference to lib.es6.d.ts I get a bunch of errors like this:

.../typings/lib.es6.d.ts(1196,2): 1169 Computed property names are not allowed in interfaces.

@mhegazy
Copy link
Contributor

mhegazy commented May 8, 2015

Which version of typescript are you using?

I gave you the wrong diffinition sorry about that. So some corrections:

  • you need to be using 1.5-beta

And add the typings:

interface Set<T> {
    add(value: T): Set<T>;
    clear(): void;
    delete(value: T): boolean;
    entries(): Array<[T, T]>;
    forEach(callbackfn: (value: T, index: T, set: Set<T>) => void, thisArg?: any): void;
    has(value: T): boolean;
    keys(): Array<T>;
    size: number;
}

interface SetConstructor {
    new <T>(): Set<T>;
    new <T>(iterable: Array<T>): Set<T>;
    prototype: Set<any>;
}
declare var Set: SetConstructor;

@JsonFreeman we should remove the restriction on computer properties in interfaces..right?

@rbuckton is getting a correct es6 typing file ready; @rbuckton please share it with @robianmcd

@JsonFreeman
Copy link
Contributor

@mhegazy Why do you want to remove the restriction on computed properties in interfaces?

@mhegazy
Copy link
Contributor

mhegazy commented May 18, 2015

currently you can not write a declaration file that uses symbols and get it to work in ES5 and ES6, you have to write two. i think this is artificial. we need to allow the use of Symbols and the use of computed properties in both. this way if you are using lib.d.ts you are not getting ES6 types, but if you deliberately use lib.es6.d.ts you can still use that with target ES5.

@mhegazy mhegazy added Bug A bug in TypeScript and removed Question An issue which isn't directly actionable in code labels May 18, 2015
@mhegazy
Copy link
Contributor

mhegazy commented May 18, 2015

@JsonFreeman let's chat about what and when we need to do this

@DanielRosenwasser
Copy link
Member

we need to allow the use of Symbols and the use of computed properties in both

I think this fits well for people who are using a polyfill anyway.

@JsonFreeman
Copy link
Contributor

We do allow computed properties downlevel. So there is nothing to do for that. In terms of Symbols, we do support polyfilling symbols in ES5. You just have to provide the typings yourself. Are you suggesting just to move the Symbols into the main lib.d.ts, where ES5 can see them as well?

@JsonFreeman
Copy link
Contributor

To clarify, recall that computed property names that point to known Symbols are exempt from computed property restrictions (like use in an interface). This was part of the design of Symbols.

@mhegazy
Copy link
Contributor

mhegazy commented May 19, 2015

sorry my bad. you are right. @robianmcd you can just include the lib.es6.d.ts explicitly in your project, and you should be good to go.

@mhegazy mhegazy added Question An issue which isn't directly actionable in code and removed Bug A bug in TypeScript labels May 19, 2015
@robianmcd
Copy link
Author

I thought I had been using Typescript 1.5 this whole tile but it turns out I was including it wrong in my gulpfile and it was falling back to 1.4. So I updated to 1.5 and included the lib.es6.d.ts and everything is working now.

Thanks for the help!

I'm still confused as to what ES6 features TypeScript will support, what will require this additional d.ts file and what will require third-party polyfills. But I assume there will be some more documentation on this when 1.5 is fully released so I can wait until then.

@arjunyel
Copy link

Sorry I am confused about the above discussion, I am trying to do
let test = [1, 2, 3, 4, 4, 3]; test = [...new Set(test)];

And the error is 'Type 'Set' is not an array type.'

I'm not using any polyfill, this works natively in Chrome so should this issue be reopened?

@RyanCavanaugh
Copy link
Member

@arjunyel this is a correct error if targeting ES5 because there isn't default ES5 codegen for iterating a Set. Specify --target ES6 or --downlevelIteration

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

6 participants