You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ES2019 Object.fromEntries uses PropertyKeys as mapped key type #31393
// A *self-contained* demonstration of the problem follows...// Test this by running `tsc` on the command-line, rather than through another build tool such as Gulp, Webpack, etc.typeT={}consta: {[key: string]: T}={"key": {}}constb: [string,T][]=Object.entries(a)constc : {[key: number]: T;[key: string]: T}=Object.fromEntries(b)constd : {[key: string]: T}=Object.fromEntries(b)
Expected behavior:
Compilation should fail because number is not a key of a.
edit: The return type of Object.fromEntries(b) should be inferred as d: { [key: string]: T } .
Actual behavior:
edit: The return type of Object.fromEntries(b) is {[key: number]: T; [key: string]: T } Adding an erroneous [key: number].
Even with the desired behaviour I think c would compile. I've edited my case to show what I expect to happen more clearly. (Namely the return type of Object.fromEntries taking the key type information from the tuple array instead of PropertyKey)
I believe this is also causing an error in our project. I have distilled the error down to the following simple repo which I think is the same issue Alex Ware (@AWare) is describing here.
When I run npm run build-good this simple example builds as expected. However, if I then go and run npm run build-bad I get the following error:
The only difference in the "bad" build is that i've set "keyofStringsOnly": true instead of false. This is a stripped down version of my actual configuration but I believe it is just the interaction of "keyofStringsOnly":true and lib:["esnext"] that is relevant to this issue.
Got the same issue randomly, not sure what triggered it as things were compiling fine. But using a target of either esnext or es2019 will cause this compilation issue. Also confirmed this by updating to typescript@next and running the same code.
Replication details are as follows, I did this in my /tmp directory and you can pretty much copy and paste these steps to reproduce.
Running tsc will complain that it has nothing to do, so touch index.ts.
Then running the tsc command will result in the following error:
*chop*/typescript/lib/lib.es2019.object.d.ts:28:81 - error TS2322: Type 'string | number | symbol' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
28 fromEntries<T = any>(entries: Iterable<readonly [PropertyKey, T]>): { [k in PropertyKey]: T };
~~~~~~~~~~~
Found 1 error.
This is specifically part of es2019 (currently esnext aliases this I believe).
The fix, for now, is to "target": "es2018" instead in your tsconfig.json.
changed the title [-]ES2019 Object.fromEntries adds new key types to generated object[/-][+]ES2019 Object.fromEntries uses PropertyKeys as mapped key type[/+]on Jan 13, 2020
It sounds like there are really two bugs here: the more serious is that the current definition of fromEntries errors when keyofStringsOnly: true. The cause (and likely fix) is similar to the original bug so I'm not going to open a new bug, though.
I see 3 possible fixes for these two bugs:
Do nothing -- this has been a bug for a couple versions of TS already.
Add a type parameter for the key type K extends PropertyKey. This is what Alex Ware (@AWare) suggests, but it doesn't fix the second bug.
Simplify the key type to string instead of PropertyKey. This fixes both bugs raised here, but may break other code. The related issues the OP links have some discussion of this.
Because this isn't a 3.8 regression, I'm not going to fix this in the 3.8 beta period — any change to the DOM types is going to break someone. I'll look at this when 3.9 starts.
Is there a motivation for why a more precise typing like that would be unsafe at the library level? I use enums a lot as keys and I'd like for mapping across them to preserve the fact that the keys are from my enum, not just a string or maybe a number or something.
Reacted by Jason Hoetger, Stefan M. Kudwien, Yuzuki Arai and Guillaume Esquevin
Activity
RyanCavanaugh commentedon May 17, 2019
Which line are you expecting to fail?
c? Why?AWare commentedon May 18, 2019
Sorry Ryan Cavanaugh (@RyanCavanaugh) I didn't explain my test case correctly.
Even with the desired behaviour I think
cwould compile. I've edited my case to show what I expect to happen more clearly. (Namely the return type ofObject.fromEntriestaking the key type information from the tuple array instead ofPropertyKey)AWare commentedon May 21, 2019
Ryan Cavanaugh (@RyanCavanaugh) Would you mind if I attempted this and raised a PR please?
donkeytronkilla commentedon Jun 18, 2019
I believe this is also causing an error in our project. I have distilled the error down to the following simple repo which I think is the same issue Alex Ware (@AWare) is describing here.
package.json:
tsconfig.good.json:
tsconfig.bad.json:
index.ts:
When I run
npm run build-goodthis simple example builds as expected. However, if I then go and runnpm run build-badI get the following error:The only difference in the "bad" build is that i've set "keyofStringsOnly": true instead of false. This is a stripped down version of my actual configuration but I believe it is just the interaction of "keyofStringsOnly":true and lib:["esnext"] that is relevant to this issue.
ipanasenko commentedon Jul 9, 2019
Having same issue on my side, same configuration (
"keyofStringsOnly": true)matt-usurp commentedon Aug 21, 2019
Got the same issue randomly, not sure what triggered it as things were compiling fine. But using a target of either
esnextores2019will cause this compilation issue. Also confirmed this by updating totypescript@nextand running the same code.Replication details are as follows, I did this in my
/tmpdirectory and you can pretty much copy and paste these steps to reproduce.tsconfig.json
{ "compilerOptions": { "target": "es2019", "keyofStringsOnly": true, }, }Running
tscwill complain that it has nothing to do, sotouch index.ts.Then running the
tsccommand will result in the following error:This is specifically part of
es2019(currentlyesnextaliases this I believe).The fix, for now, is to
"target": "es2018"instead in yourtsconfig.json.{ "compilerOptions": { "target": "es2018", "keyofStringsOnly": true, }, }jpandl19 commentedon Oct 26, 2019
I changed
targetto"target": "es2018",but I am still getting the following error:Here is my
tsconfig.json{ "compilerOptions": { "target": "es2018", "moduleResolution": "node", "module": "commonjs", "sourceMap": true, "rootDir": "src", "outDir": "dist", "keyofStringsOnly": true, "lib": ["esnext", "dom"], "esModuleInterop": true, }, "exclude": ["node_modules", "**/*.spec.ts"] }The only thing that works is removing
"keyofStringsOnly": true,.I am not sure why this is still happening. Has anyone else experienced this/ any suggestions on a fix?
[-]ES2019 Object.fromEntries adds new key types to generated object[/-][+]ES2019 Object.fromEntries uses PropertyKeys as mapped key type[/+]sandersn commentedon Jan 13, 2020
It sounds like there are really two bugs here: the more serious is that the current definition of
fromEntrieserrors whenkeyofStringsOnly: true. The cause (and likely fix) is similar to the original bug so I'm not going to open a new bug, though.I see 3 possible fixes for these two bugs:
K extends PropertyKey. This is what Alex Ware (@AWare) suggests, but it doesn't fix the second bug.stringinstead ofPropertyKey. This fixes both bugs raised here, but may break other code. The related issues the OP links have some discussion of this.Because this isn't a 3.8 regression, I'm not going to fix this in the 3.8 beta period — any change to the DOM types is going to break someone. I'll look at this when 3.9 starts.
nashspence commentedon Feb 2, 2020
Is there a particularly good workaround for this in the meantime without setting
keyofStringsOnly: false?*edit - for now I have set
"skipDefaultLibCheck": truewhich seems okayosdiab commentedon Mar 14, 2020
My question is this: I want
Object.fromEntries()to be generic on the key type, something like this:Is there a motivation for why a more precise typing like that would be unsafe at the library level? I use enums a lot as keys and I'd like for mapping across them to preserve the fact that the keys are from my enum, not just a string or maybe a number or something.
Simplify return type of Object.fromEntries
sandersn commentedon Mar 18, 2020
I opened #37457 which makes the return type
{ [k: string]: T }. Compared to the current declaration, this just drops the numeric index signature.Simplify return type of Object.fromEntries (#37457)