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

TypeScript const assertions raise error in babel #9800

Closed
ssynix opened this issue Mar 31, 2019 · 13 comments · Fixed by #9869
Closed

TypeScript const assertions raise error in babel #9800

ssynix opened this issue Mar 31, 2019 · 13 comments · Fixed by #9869
Labels
area: typescript outdated A closed issue/PR that is archived due to age. Recommended to make a new issue pkg: parser

Comments

@ssynix
Copy link

ssynix commented Mar 31, 2019

Bug Report

Current Behavior
Some const assertions result in errors. Seems like the check introduced in this PR is too strict? Because I didn't see any errors in VSCode till I started webpack dev server.

Input Code

function foo() {
  const a = getObjectAWithLongAssType();
  const b = getObjectBWithLongAssType();

  return [a, b] as const; // no errors in tsc or vscode
  // Previously: return [a,b] as [typeof a, typeof b]
}

Expected behavior/code
VSCode outputs the expected readonly tuple type, so I don't expect any errors in babel.

Babel Configuration (.babelrc, package.json, cli command)

    "@babel/core": "^7.4.0",
    "@babel/plugin-proposal-class-properties": "^7.4.0",
    "@babel/polyfill": "^7.4.0",
    "@babel/preset-env": "^7.4.2",
    "@babel/preset-react": "^7.0.0",
    "@babel/preset-typescript": "^7.3.3",

Possible Solution

@tanhauhau is there a need for tsCheckLiteralForConstantContext to happen in babel? To me it seems like it's enough to parse as const expressions as assertions and move on, since TypeScript is actually in charge of ensuring the assertions are valid.

@babel-bot
Copy link
Collaborator

Hey @ssynix! We really appreciate you taking the time to report an issue. The collaborators
on this project attempt to help as many people as possible, but we're a limited number of volunteers,
so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack
community
that typically always has someone willing to help. You can sign-up here
for an invite.

@tanhauhau
Copy link
Member

hmm.. @nicolo-ribaudo need your advice

@nicolo-ribaudo
Copy link
Member

Ok, I downloaded TS 3.4 and apparentely we only need to check the top-level node.

e.g. This isn't valid:

(a ? 0 : 1) as const;

but this is:

[a ? 0 : 1] as const;

@ssynix
Copy link
Author

ssynix commented Mar 31, 2019

These are also valid:

const obj = {
  readonly: [1, 'foo'] as const,
  array: [1, 'foo']
};

const array = [1, 'foo', [1, 'foo'] as const] as const;

From the announcement:

  • no literal types in that expression should be widened (e.g. no going from "hello" to string)
  • object literals get readonly properties
  • array literals become readonly tuples

It doesn't seem to put any constraints on the members of those array/object literals, or that as const can only be applied to the top-level.


Does babel typically try to validate types, or simply parse them? To me (a ? 0 : 1) as const is syntactically valid TypeScript, although it's not semantically correct in this specific version of TypeScript. I don't expect any errors from babel for the same reason I don't see babel errors when I write: 'foo' as number.

@nicolo-ribaudo
Copy link
Member

To me (a ? 0 : 1) as const is syntactically valid TypeScript, although it's not semantically correct in this specific version of TypeScript.

I don't think so. If it wasn't syntax-related, those two snippets would be equivalent:

const foo = [1, 2, 3] as const;
const _tmp = [1, 2, 3] as const;
const foo = _tmp as const;

But the first is valid; the second isn't. What the "argument" to as-const is syntax-related, not type related.

@ssynix
Copy link
Author

ssynix commented Mar 31, 2019

The syntax is valid TypeScript, except that it contains typing errors. It's feasible to imagine a TypeScript version that will add support for (a ? 0 : 1) as const (i.e. 0 | 1), or for your example.

Same with 'foo' as number: we can easily determine at parse time that it's a semantic error, but Babel will happily parse it (as it should!).

We don't want to duplicate the type-checker's work in the Babel parser itself, since the TypeScript compiler is already in charge of that. Babel should emit code as if the types don't exist, and using an incorrect typing assertion should not get in the way of that.


That's my 2 cents based on the limited knowledge I have of the internals of babel, so definitely take it with a grain of salt! The main issue here is that valid const assertions are being rejected by babel in a few cases.

@DanielRosenwasser
Copy link
Member

Yeah, as const should be very permissive in the syntax which it parses. None of the semantic restrictions should be applied to Babel if it's just going to get erased anyway.

@tanhauhau
Copy link
Member

sorry for the late MR 😅

@hronro
Copy link

hronro commented Apr 26, 2019

Could someone update the version of @babel/preset-typescript so I can use the as const syntax in my project?

@ahem
Copy link

ahem commented May 9, 2019

It is great that this is merged, but is there a timeline for when it will also be released?

@clentfort
Copy link

clentfort commented May 9, 2019

The fix has been released in @babel/parser 7.4.4. 13 days ago. Check https://www.npmjs.com/package/@babel/parser/v/7.4.4 and https://github.com/babel/babel/releases/tag/v7.4.4 for more details.

@0xorial
Copy link

0xorial commented Jul 30, 2019

Should following work?

export const newData = {
  clientNumber: '082224',
} as const;

Because I am getting unexpected token error with @babel/parser@7.5.5

@tanhauhau
Copy link
Member

tanhauhau commented Jul 31, 2019

@0xorial yes refer to the repl

@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Oct 30, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Oct 30, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: typescript outdated A closed issue/PR that is archived due to age. Recommended to make a new issue pkg: parser
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants