@@ -2778,24 +2778,12 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
27782778 if ( ! init ) continue ;
27792779
27802780 // var and let aren't ever allowed initializers.
2781- //
2782- // If a const declaration has no type annotation and is initiailized to
2783- // a string literal, numeric literal, or enum reference, then it is
2784- // allowed. In an ideal world, we'd check whether init was *actually* an
2785- // enum reference, but we allow anything that "could be" a literal enum
2786- // in `isPossiblyLiteralEnum` since we don't have all the information
2787- // that the typescript compiler has.
27882781 if ( kind !== "const" || ! ! id . typeAnnotation ) {
27892782 this . raise ( TSErrors . InitializerNotAllowedInAmbientContext , {
27902783 at : init ,
27912784 } ) ;
27922785 } else if (
2793- init . type !== "StringLiteral" &&
2794- init . type !== "BooleanLiteral" &&
2795- init . type !== "NumericLiteral" &&
2796- init . type !== "BigIntLiteral" &&
2797- ( init . type !== "TemplateLiteral" || init . expressions . length > 0 ) &&
2798- ! isPossiblyLiteralEnum ( init )
2786+ ! isValidAmbientConstInitializer ( init , this . hasPlugin ( "estree" ) )
27992787 ) {
28002788 this . raise (
28012789 TSErrors . ConstInitiailizerMustBeStringOrNumericLiteralOrLiteralEnumReference ,
@@ -4112,6 +4100,68 @@ function isPossiblyLiteralEnum(expression: N.Expression): boolean {
41124100 return isUncomputedMemberExpressionChain ( expression . object ) ;
41134101}
41144102
4103+ // If a const declaration has no type annotation and is initiailized to
4104+ // a string literal, numeric literal, or enum reference, then it is
4105+ // allowed. In an ideal world, we'd check whether init was *actually* an
4106+ // enum reference, but we allow anything that "could be" a literal enum
4107+ // in `isPossiblyLiteralEnum` since we don't have all the information
4108+ // that the typescript compiler has.
4109+ function isValidAmbientConstInitializer (
4110+ expression : N . Expression ,
4111+ estree : boolean ,
4112+ ) : boolean {
4113+ const { type } = expression ;
4114+ if ( expression . extra ?. parenthesized ) {
4115+ return false ;
4116+ }
4117+ if ( estree ) {
4118+ if ( type === "Literal" ) {
4119+ const { value } = expression ;
4120+ if ( typeof value === "string" || typeof value === "boolean" ) {
4121+ return true ;
4122+ }
4123+ }
4124+ } else {
4125+ if ( type === "StringLiteral" || type === "BooleanLiteral" ) {
4126+ return true ;
4127+ }
4128+ }
4129+ if ( isNumber ( expression , estree ) || isNegativeNumber ( expression , estree ) ) {
4130+ return true ;
4131+ }
4132+ if ( type === "TemplateLiteral" && expression . expressions . length === 0 ) {
4133+ return true ;
4134+ }
4135+ if ( isPossiblyLiteralEnum ( expression ) ) {
4136+ return true ;
4137+ }
4138+ return false ;
4139+ }
4140+
4141+ function isNumber ( expression : N . Expression , estree : boolean ) : boolean {
4142+ if ( estree ) {
4143+ return (
4144+ expression . type === "Literal" &&
4145+ ( typeof expression . value === "number" || "bigint" in expression )
4146+ ) ;
4147+ } else {
4148+ return (
4149+ expression . type === "NumericLiteral" ||
4150+ expression . type === "BigIntLiteral"
4151+ ) ;
4152+ }
4153+ }
4154+
4155+ function isNegativeNumber ( expression : N . Expression , estree : boolean ) : boolean {
4156+ if ( expression . type === "UnaryExpression" ) {
4157+ const { operator, argument } = expression as N . UnaryExpression ;
4158+ if ( operator === "-" && isNumber ( argument , estree ) ) {
4159+ return true ;
4160+ }
4161+ }
4162+ return false ;
4163+ }
4164+
41154165function isUncomputedMemberExpressionChain ( expression : N . Expression ) : boolean {
41164166 if ( expression . type === "Identifier" ) return true ;
41174167 if ( expression . type !== "MemberExpression" ) return false ;
0 commit comments