babel / babel

🐠 Babel is a compiler for writing next generation JavaScript.

Home Page:https://babel.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TypeScript const assertions raise error in babel

ssynix opened this issue · comments

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.

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.

hmm.. @nicolo-ribaudo need your advice

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;

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.

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.

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.

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.

sorry for the late MR 😅

commented

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

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

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.

Should following work?

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

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

@0xorial yes refer to the repl