fix35982: allow BigIntLiteral to parse as PropertyName for literal object and indices (#58608)

This commit is contained in:
Isabel Duan
2024-07-19 17:48:08 -07:00
committed by GitHub
parent 85d6bb6fe6
commit dfb870150c
22 changed files with 1057 additions and 126 deletions
+10 -2
View File
@@ -18772,14 +18772,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
if (accessNode) {
const indexNode = getIndexNodeForAccessExpression(accessNode);
if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
if (indexNode.kind !== SyntaxKind.BigIntLiteral && indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, "" + (indexType as StringLiteralType | NumberLiteralType).value, typeToString(objectType));
}
else if (indexType.flags & (TypeFlags.String | TypeFlags.Number)) {
error(indexNode, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType));
}
else {
error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType));
const typeString = indexNode.kind === SyntaxKind.BigIntLiteral ? "bigint" : typeToString(indexType);
error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeString);
}
}
if (isTypeAny(indexType)) {
@@ -43908,6 +43909,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return;
}
if (node.name.kind === SyntaxKind.BigIntLiteral) {
error(node.name, Diagnostics.A_bigint_literal_cannot_be_used_as_a_property_name);
}
const type = convertAutoToAny(getTypeOfSymbol(symbol));
if (node === symbol.valueDeclaration) {
// Node is the primary declaration of the symbol, just validate the initializer
@@ -51114,6 +51119,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (name.kind === SyntaxKind.NumericLiteral) {
checkGrammarNumericLiteral(name);
}
if (name.kind === SyntaxKind.BigIntLiteral) {
addErrorOrSuggestion(/*isError*/ true, createDiagnosticForNode(name, Diagnostics.A_bigint_literal_cannot_be_used_as_a_property_name));
}
currentKind = DeclarationMeaning.PropertyAssignment;
break;
case SyntaxKind.MethodDeclaration:
+4
View File
@@ -1809,6 +1809,10 @@
"category": "Error",
"code": 1538
},
"A 'bigint' literal cannot be used as a property name.": {
"category": "Error",
"code": 1539
},
"The types of '{0}' are incompatible between these types.": {
"category": "Error",
+6 -3
View File
@@ -14,6 +14,7 @@ import {
attachFileToDiagnostics,
AwaitExpression,
BaseNodeFactory,
BigIntLiteral,
BinaryExpression,
BinaryOperatorToken,
BindingElement,
@@ -2692,7 +2693,8 @@ namespace Parser {
function isLiteralPropertyName(): boolean {
return tokenIsIdentifierOrKeyword(token()) ||
token() === SyntaxKind.StringLiteral ||
token() === SyntaxKind.NumericLiteral;
token() === SyntaxKind.NumericLiteral ||
token() === SyntaxKind.BigIntLiteral;
}
function isImportAttributeName(): boolean {
@@ -2700,8 +2702,8 @@ namespace Parser {
}
function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName {
if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) {
const node = parseLiteralNode() as StringLiteral | NumericLiteral;
if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral) {
const node = parseLiteralNode() as StringLiteral | NumericLiteral | BigIntLiteral;
node.text = internIdentifier(node.text);
return node;
}
@@ -8058,6 +8060,7 @@ namespace Parser {
tokenIsIdentifierOrKeyword(token()) ||
token() === SyntaxKind.StringLiteral ||
token() === SyntaxKind.NumericLiteral ||
token() === SyntaxKind.BigIntLiteral ||
token() === SyntaxKind.AsteriskToken ||
token() === SyntaxKind.OpenBracketToken
) {
+2 -1
View File
@@ -23,6 +23,7 @@ import {
isArrayBindingElement,
isArrayBindingOrAssignmentElement,
isArrayBindingOrAssignmentPattern,
isBigIntLiteral,
isBindingElement,
isBindingName,
isBindingOrAssignmentElement,
@@ -558,7 +559,7 @@ function createDestructuringPropertyAccess(flattenContext: FlattenContext, value
const argumentExpression = ensureIdentifier(flattenContext, Debug.checkDefined(visitNode(propertyName.expression, flattenContext.visitor, isExpression)), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName);
return flattenContext.context.factory.createElementAccessExpression(value, argumentExpression);
}
else if (isStringOrNumericLiteralLike(propertyName)) {
else if (isStringOrNumericLiteralLike(propertyName) || isBigIntLiteral(propertyName)) {
const argumentExpression = factory.cloneNode(propertyName);
return flattenContext.context.factory.createElementAccessExpression(value, argumentExpression);
}
+11 -3
View File
@@ -1721,7 +1721,14 @@ export interface QualifiedName extends Node, FlowContainer {
export type EntityName = Identifier | QualifiedName;
export type PropertyName = Identifier | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier;
export type PropertyName =
| Identifier
| StringLiteral
| NoSubstitutionTemplateLiteral
| NumericLiteral
| ComputedPropertyName
| PrivateIdentifier
| BigIntLiteral;
export type MemberName = Identifier | PrivateIdentifier;
@@ -2340,7 +2347,8 @@ export interface LiteralTypeNode extends TypeNode {
export interface StringLiteral extends LiteralExpression, Declaration {
readonly kind: SyntaxKind.StringLiteral;
/** @internal */ readonly textSourceNode?: Identifier | StringLiteralLike | NumericLiteral | PrivateIdentifier | JsxNamespacedName; // Allows a StringLiteral to get its text from another node (used by transforms).
/** @internal */
readonly textSourceNode?: Identifier | StringLiteralLike | NumericLiteral | PrivateIdentifier | JsxNamespacedName | BigIntLiteral; // Allows a StringLiteral to get its text from another node (used by transforms).
/**
* Note: this is only set when synthesizing a node, not during parsing.
*
@@ -2350,7 +2358,7 @@ export interface StringLiteral extends LiteralExpression, Declaration {
}
export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName;
export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName | BigIntLiteral;
export interface TemplateLiteralTypeNode extends TypeNode {
kind: SyntaxKind.TemplateLiteralType;
+2
View File
@@ -2207,6 +2207,7 @@ export function tryGetTextOfPropertyName(name: PropertyName | NoSubstitutionTemp
return name.emitNode?.autoGenerate ? undefined : name.escapedText;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return escapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
@@ -5221,6 +5222,7 @@ export function getPropertyNameForPropertyNameNode(name: PropertyName | JsxAttri
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
return escapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
const nameExpression = name.expression;
+2 -2
View File
@@ -4422,7 +4422,7 @@ declare namespace ts {
readonly right: Identifier;
}
type EntityName = Identifier | QualifiedName;
type PropertyName = Identifier | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier;
type PropertyName = Identifier | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier | BigIntLiteral;
type MemberName = Identifier | PrivateIdentifier;
type DeclarationName = PropertyName | JsxAttributeName | StringLiteralLike | ElementAccessExpression | BindingPattern | EntityNameExpression;
interface Declaration extends Node {
@@ -4773,7 +4773,7 @@ declare namespace ts {
readonly kind: SyntaxKind.StringLiteral;
}
type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName;
type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName | BigIntLiteral;
interface TemplateLiteralTypeNode extends TypeNode {
kind: SyntaxKind.TemplateLiteralType;
readonly head: TemplateHead;
@@ -0,0 +1,69 @@
badExport.ts(1,10): error TS2304: Cannot find name 'foo'.
badExport.ts(1,17): error TS1003: Identifier expected.
badExport.ts(1,20): error TS1128: Declaration or statement expected.
badExport2.ts(1,10): error TS1003: Identifier expected.
badExport2.ts(1,16): error TS2304: Cannot find name 'foo'.
badExport2.ts(1,20): error TS1128: Declaration or statement expected.
badImport.ts(1,10): error TS1003: Identifier expected.
badImport.ts(1,10): error TS1141: String literal expected.
badImport.ts(1,20): error TS1128: Declaration or statement expected.
badImport.ts(1,22): error TS1434: Unexpected keyword or identifier.
badImport.ts(1,22): error TS2304: Cannot find name 'from'.
badImport2.ts(1,17): error TS1003: Identifier expected.
badImport2.ts(1,17): error TS1141: String literal expected.
badImport2.ts(1,20): error TS1128: Declaration or statement expected.
badImport2.ts(1,22): error TS1434: Unexpected keyword or identifier.
badImport2.ts(1,22): error TS2304: Cannot find name 'from'.
==== foo.ts (0 errors) ====
const foo = 0n;
export { foo as "0n" };
==== correctUse.ts (0 errors) ====
import { "0n" as foo } from "./foo";
export { foo as "0n" };
==== badImport.ts (5 errors) ====
import { 0n as foo } from "./foo";
~~
!!! error TS1003: Identifier expected.
~~~~~~~~~
!!! error TS1141: String literal expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~
!!! error TS1434: Unexpected keyword or identifier.
~~~~
!!! error TS2304: Cannot find name 'from'.
==== badImport2.ts (5 errors) ====
import { foo as 0n } from "./foo";
~~
!!! error TS1003: Identifier expected.
~~
!!! error TS1141: String literal expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~
!!! error TS1434: Unexpected keyword or identifier.
~~~~
!!! error TS2304: Cannot find name 'from'.
==== badExport.ts (3 errors) ====
export { foo as 0n };
~~~
!!! error TS2304: Cannot find name 'foo'.
~~
!!! error TS1003: Identifier expected.
~
!!! error TS1128: Declaration or statement expected.
==== badExport2.ts (3 errors) ====
export { 0n as foo };
~~
!!! error TS1003: Identifier expected.
~~~
!!! error TS2304: Cannot find name 'foo'.
~
!!! error TS1128: Declaration or statement expected.
@@ -0,0 +1,44 @@
//// [tests/cases/compiler/bigintArbirtraryIdentifier.ts] ////
//// [foo.ts]
const foo = 0n;
export { foo as "0n" };
//// [correctUse.ts]
import { "0n" as foo } from "./foo";
export { foo as "0n" };
//// [badImport.ts]
import { 0n as foo } from "./foo";
//// [badImport2.ts]
import { foo as 0n } from "./foo";
//// [badExport.ts]
export { foo as 0n };
//// [badExport2.ts]
export { 0n as foo };
//// [foo.js]
const foo = 0n;
export { foo as "0n" };
//// [correctUse.js]
import { "0n" as foo } from "./foo";
export { foo as "0n" };
//// [badImport.js]
from;
"./foo";
export {};
//// [badImport2.js]
from;
"./foo";
export {};
//// [badExport.js]
export { foo as };
0n;
;
//// [badExport2.js]
0n;
;
export {};
@@ -0,0 +1,34 @@
//// [tests/cases/compiler/bigintArbirtraryIdentifier.ts] ////
=== foo.ts ===
const foo = 0n;
>foo : Symbol(foo, Decl(foo.ts, 0, 5))
export { foo as "0n" };
>foo : Symbol(foo, Decl(foo.ts, 0, 5))
>"0n" : Symbol("0n", Decl(foo.ts, 1, 8))
=== correctUse.ts ===
import { "0n" as foo } from "./foo";
>foo : Symbol(foo, Decl(correctUse.ts, 0, 8))
export { foo as "0n" };
>foo : Symbol(foo, Decl(correctUse.ts, 0, 8))
>"0n" : Symbol("0n", Decl(correctUse.ts, 1, 8))
=== badImport.ts ===
import { 0n as foo } from "./foo";
>foo : Symbol(foo)
=== badImport2.ts ===
import { foo as 0n } from "./foo";
> : Symbol((Missing), Decl(badImport2.ts, 0, 8))
=== badExport.ts ===
export { foo as 0n };
> : Symbol((Missing), Decl(badExport.ts, 0, 8))
=== badExport2.ts ===
export { 0n as foo };
>foo : Symbol(foo)
@@ -0,0 +1,64 @@
//// [tests/cases/compiler/bigintArbirtraryIdentifier.ts] ////
=== foo.ts ===
const foo = 0n;
>foo : 0n
> : ^^
>0n : 0n
> : ^^
export { foo as "0n" };
>foo : 0n
> : ^^
>"0n" : 0n
> : ^^
=== correctUse.ts ===
import { "0n" as foo } from "./foo";
>foo : 0n
> : ^^
export { foo as "0n" };
>foo : 0n
> : ^^
>"0n" : 0n
> : ^^
=== badImport.ts ===
import { 0n as foo } from "./foo";
>0n as foo : foo
> : ^^^
>0n : 0n
> : ^^
>from : any
> : ^^^
>"./foo" : "./foo"
> : ^^^^^^^
=== badImport2.ts ===
import { foo as 0n } from "./foo";
>foo : any
> : ^^^
> : any
> : ^^^
>from : any
> : ^^^
>"./foo" : "./foo"
> : ^^^^^^^
=== badExport.ts ===
export { foo as 0n };
>foo : any
> : ^^^
> : any
> : ^^^
>0n : 0n
> : ^^
=== badExport2.ts ===
export { 0n as foo };
>0n as foo : foo
> : ^^^
>0n : 0n
> : ^^
@@ -1,15 +1,11 @@
a.ts(2,6): error TS1268: An index signature parameter type must be 'string', 'number', 'symbol', or a template literal type.
a.ts(8,11): error TS2538: Type '1n' cannot be used as an index type.
a.ts(14,1): error TS2322: Type 'bigint' is not assignable to type 'string | number | symbol'.
a.ts(19,12): error TS2538: Type 'bigint' cannot be used as an index type.
b.ts(2,12): error TS1136: Property assignment expected.
b.ts(2,14): error TS1005: ';' expected.
b.ts(2,19): error TS1128: Declaration or statement expected.
b.ts(3,12): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
b.ts(4,12): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
a.ts(8,11): error TS2538: Type 'bigint' cannot be used as an index type.
a.ts(9,17): error TS2538: Type 'bigint' cannot be used as an index type.
a.ts(15,1): error TS2322: Type 'bigint' is not assignable to type 'string | number | symbol'.
a.ts(20,12): error TS2538: Type 'bigint' cannot be used as an index type.
==== a.ts (4 errors) ====
==== a.ts (5 errors) ====
interface BigIntIndex<E> {
[index: bigint]: E; // should error
~~~~~
@@ -21,7 +17,10 @@ b.ts(4,12): error TS2464: A computed property name must be of type 'string', 'nu
num = arr["1"];
num = arr[1n]; // should error
~~
!!! error TS2538: Type '1n' cannot be used as an index type.
!!! error TS2538: Type 'bigint' cannot be used as an index type.
num = [1, 2, 3][1n]; // should error
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
let key: keyof any; // should be type "string | number | symbol"
key = 123;
@@ -40,21 +39,4 @@ b.ts(4,12): error TS2464: A computed property name must be of type 'string', 'nu
typedArray[String(bigNum)] = 0xAA;
typedArray["1"] = 0xBB;
typedArray[2] = 0xCC;
// {1n: 123} is a syntax error; must go in separate file so BigIntIndex error is shown
==== b.ts (5 errors) ====
// BigInt cannot be used as an object literal property
const a = {1n: 123};
~~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ';' expected.
~
!!! error TS1128: Declaration or statement expected.
const b = {[1n]: 456};
~~~~
!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
const c = {[bigNum]: 789};
~~~~~~~~
!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
+2 -16
View File
@@ -9,6 +9,7 @@ const arr: number[] = [1, 2, 3];
let num: number = arr[1];
num = arr["1"];
num = arr[1n]; // should error
num = [1, 2, 3][1n]; // should error
let key: keyof any; // should be type "string | number | symbol"
key = 123;
@@ -23,13 +24,6 @@ typedArray[bigNum] = 0xAA; // should error
typedArray[String(bigNum)] = 0xAA;
typedArray["1"] = 0xBB;
typedArray[2] = 0xCC;
// {1n: 123} is a syntax error; must go in separate file so BigIntIndex error is shown
//// [b.ts]
// BigInt cannot be used as an object literal property
const a = {1n: 123};
const b = {[1n]: 456};
const c = {[bigNum]: 789};
//// [a.js]
@@ -37,6 +31,7 @@ const arr = [1, 2, 3];
let num = arr[1];
num = arr["1"];
num = arr[1n]; // should error
num = [1, 2, 3][1n]; // should error
let key; // should be type "string | number | symbol"
key = 123;
key = "abc";
@@ -49,12 +44,3 @@ typedArray[bigNum] = 0xAA; // should error
typedArray[String(bigNum)] = 0xAA;
typedArray["1"] = 0xBB;
typedArray[2] = 0xCC;
// {1n: 123} is a syntax error; must go in separate file so BigIntIndex error is shown
//// [b.js]
// BigInt cannot be used as an object literal property
const a = {};
1n;
123;
;
const b = { [1n]: 456 };
const c = { [bigNum]: 789 };
+16 -28
View File
@@ -25,57 +25,45 @@ num = arr[1n]; // should error
>num : Symbol(num, Decl(a.ts, 5, 3))
>arr : Symbol(arr, Decl(a.ts, 4, 5))
num = [1, 2, 3][1n]; // should error
>num : Symbol(num, Decl(a.ts, 5, 3))
let key: keyof any; // should be type "string | number | symbol"
>key : Symbol(key, Decl(a.ts, 9, 3))
>key : Symbol(key, Decl(a.ts, 10, 3))
key = 123;
>key : Symbol(key, Decl(a.ts, 9, 3))
>key : Symbol(key, Decl(a.ts, 10, 3))
key = "abc";
>key : Symbol(key, Decl(a.ts, 9, 3))
>key : Symbol(key, Decl(a.ts, 10, 3))
key = Symbol();
>key : Symbol(key, Decl(a.ts, 9, 3))
>key : Symbol(key, Decl(a.ts, 10, 3))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
key = 123n; // should error
>key : Symbol(key, Decl(a.ts, 9, 3))
>key : Symbol(key, Decl(a.ts, 10, 3))
// Show correct usage of bigint index: explicitly convert to string
const bigNum: bigint = 0n;
>bigNum : Symbol(bigNum, Decl(a.ts, 16, 5))
>bigNum : Symbol(bigNum, Decl(a.ts, 17, 5))
const typedArray = new Uint8Array(3);
>typedArray : Symbol(typedArray, Decl(a.ts, 17, 5))
>typedArray : Symbol(typedArray, Decl(a.ts, 18, 5))
>Uint8Array : Symbol(Uint8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 1 more)
typedArray[bigNum] = 0xAA; // should error
>typedArray : Symbol(typedArray, Decl(a.ts, 17, 5))
>bigNum : Symbol(bigNum, Decl(a.ts, 16, 5))
>typedArray : Symbol(typedArray, Decl(a.ts, 18, 5))
>bigNum : Symbol(bigNum, Decl(a.ts, 17, 5))
typedArray[String(bigNum)] = 0xAA;
>typedArray : Symbol(typedArray, Decl(a.ts, 17, 5))
>typedArray : Symbol(typedArray, Decl(a.ts, 18, 5))
>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --) ... and 4 more)
>bigNum : Symbol(bigNum, Decl(a.ts, 16, 5))
>bigNum : Symbol(bigNum, Decl(a.ts, 17, 5))
typedArray["1"] = 0xBB;
>typedArray : Symbol(typedArray, Decl(a.ts, 17, 5))
>typedArray : Symbol(typedArray, Decl(a.ts, 18, 5))
typedArray[2] = 0xCC;
>typedArray : Symbol(typedArray, Decl(a.ts, 17, 5))
// {1n: 123} is a syntax error; must go in separate file so BigIntIndex error is shown
=== b.ts ===
// BigInt cannot be used as an object literal property
const a = {1n: 123};
>a : Symbol(a, Decl(b.ts, 1, 5))
const b = {[1n]: 456};
>b : Symbol(b, Decl(b.ts, 2, 5))
>[1n] : Symbol([1n], Decl(b.ts, 2, 11))
const c = {[bigNum]: 789};
>c : Symbol(c, Decl(b.ts, 3, 5))
>[bigNum] : Symbol([bigNum], Decl(b.ts, 3, 11))
>bigNum : Symbol(bigNum, Decl(a.ts, 16, 5))
>typedArray : Symbol(typedArray, Decl(a.ts, 18, 5))
+18 -37
View File
@@ -53,6 +53,24 @@ num = arr[1n]; // should error
>1n : 1n
> : ^^
num = [1, 2, 3][1n]; // should error
>num = [1, 2, 3][1n] : any
> : ^^^
>num : number
> : ^^^^^^
>[1, 2, 3][1n] : any
> : ^^^
>[1, 2, 3] : number[]
> : ^^^^^^^^
>1 : 1
> : ^
>2 : 2
> : ^
>3 : 3
> : ^
>1n : 1n
> : ^^
let key: keyof any; // should be type "string | number | symbol"
>key : string | number | symbol
> : ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -160,40 +178,3 @@ typedArray[2] = 0xCC;
>0xCC : 204
> : ^^^
// {1n: 123} is a syntax error; must go in separate file so BigIntIndex error is shown
=== b.ts ===
// BigInt cannot be used as an object literal property
const a = {1n: 123};
>a : {}
> : ^^
>{ : {}
> : ^^
>1n : 1n
> : ^^
>123 : 123
> : ^^^
const b = {[1n]: 456};
>b : {}
> : ^^
>{[1n]: 456} : {}
> : ^^
>[1n] : number
> : ^^^^^^
>1n : 1n
> : ^^
>456 : 456
> : ^^^
const c = {[bigNum]: 789};
>c : {}
> : ^^
>{[bigNum]: 789} : {}
> : ^^
>[bigNum] : number
> : ^^^^^^
>bigNum : bigint
> : ^^^^^^
>789 : 789
> : ^^^
@@ -0,0 +1,143 @@
a.ts(2,5): error TS1539: A 'bigint' literal cannot be used as a property name.
a.ts(5,13): error TS1539: A 'bigint' literal cannot be used as a property name.
a.ts(6,13): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
a.ts(7,13): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
a.ts(12,9): error TS2538: Type 'bigint' cannot be used as an index type.
a.ts(15,13): error TS1539: A 'bigint' literal cannot be used as a property name.
g.ts(2,5): error TS1539: A 'bigint' literal cannot be used as a property name.
g.ts(8,5): error TS1539: A 'bigint' literal cannot be used as a property name.
g.ts(15,17): error TS1539: A 'bigint' literal cannot be used as a property name.
g.ts(17,3): error TS2538: Type 'bigint' cannot be used as an index type.
g.ts(18,4): error TS2538: Type 'bigint' cannot be used as an index type.
g.ts(20,7): error TS2741: Property '"3n"' is missing in type '{}' but required in type 'H'.
g.ts(20,17): error TS1539: A 'bigint' literal cannot be used as a property name.
g.ts(22,3): error TS2538: Type 'bigint' cannot be used as an index type.
g.ts(23,4): error TS2538: Type 'bigint' cannot be used as an index type.
g.ts(25,17): error TS1539: A 'bigint' literal cannot be used as a property name.
g.ts(27,3): error TS2538: Type 'bigint' cannot be used as an index type.
g.ts(28,4): error TS2538: Type 'bigint' cannot be used as an index type.
g.ts(30,7): error TS2741: Property '"5n"' is missing in type '{}' but required in type 'L'.
g.ts(30,17): error TS1539: A 'bigint' literal cannot be used as a property name.
g.ts(31,18): error TS2322: Type 'string' is not assignable to type 'number'.
g.ts(32,3): error TS2538: Type 'bigint' cannot be used as an index type.
g.ts(33,4): error TS2538: Type 'bigint' cannot be used as an index type.
g.ts(35,1): error TS1434: Unexpected keyword or identifier.
g.ts(35,2): error TS1353: A bigint literal must be an integer.
q.ts(2,19): error TS2322: Type 'bigint' is not assignable to type 'string | number | symbol'.
Type 'bigint' is not assignable to type 'string | number | symbol'.
==== a.ts (6 errors) ====
// BigInt cannot be used as an object literal property
{ ({1n: 123}); };
~~
!!! error TS1539: A 'bigint' literal cannot be used as a property name.
const bigNum: bigint = 0n;
const a = { 1n: 123 };
~~
!!! error TS1539: A 'bigint' literal cannot be used as a property name.
const b = { [1n]: 456 };
~~~~
!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
const c = { [bigNum]: 789 };
~~~~~~~~
!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
const arr = [1, 2, 3] as const;
const { 0: d } = arr;
const { "0": e } = arr;
const { 0n: f } = arr; // bigint should give an index error
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
// BigInt cannot be used as an property name
const x = { 0n: 123 };
~~
!!! error TS1539: A 'bigint' literal cannot be used as a property name.
==== g.ts (19 errors) ====
interface G {
2n: string;
~~
!!! error TS1539: A 'bigint' literal cannot be used as a property name.
}
interface H {
"3n": string;
}
class K {
4n = 0;
~~
!!! error TS1539: A 'bigint' literal cannot be used as a property name.
}
class L {
"5n" = 0;
}
const g : G = { 2n: "propertyNameError2" };
~~
!!! error TS1539: A 'bigint' literal cannot be used as a property name.
const g2 : G = { "2n": "ok2" };
g[2n];
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
g2[2n];
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
const h : H = { 3n: "propertyNameErrorAndMissingProperty3" };
~
!!! error TS2741: Property '"3n"' is missing in type '{}' but required in type 'H'.
!!! related TS2728 g.ts:5:5: '"3n"' is declared here.
~~
!!! error TS1539: A 'bigint' literal cannot be used as a property name.
const h2 : H = { "3n": "ok3" };
h[3n];
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
h2[3n];
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
const k : K = { 4n: "propertyNameError4" };
~~
!!! error TS1539: A 'bigint' literal cannot be used as a property name.
const k2 : K = { "4n": "ok4" };
k[4n];
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
k2[4n];
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
const l : L = { 5n: "propertyNameErrorAndMissingProperty5" };
~
!!! error TS2741: Property '"5n"' is missing in type '{}' but required in type 'L'.
!!! related TS2728 g.ts:12:5: '"5n"' is declared here.
~~
!!! error TS1539: A 'bigint' literal cannot be used as a property name.
const l2 : L = { "5n": "ok4" };
~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
!!! related TS6500 g.ts:12:5: The expected type comes from property '5n' which is declared here on type 'L'
l[5n];
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
l2[5n];
~~
!!! error TS2538: Type 'bigint' cannot be used as an index type.
g.2n; // not valid JS
~
!!! error TS1434: Unexpected keyword or identifier.
~~~
!!! error TS1353: A bigint literal must be an integer.
==== q.ts (1 errors) ====
type Q = 6n | 7n | 8n;
type T = { [t in Q]: string };
~
!!! error TS2322: Type 'bigint' is not assignable to type 'string | number | symbol'.
!!! error TS2322: Type 'bigint' is not assignable to type 'string | number | symbol'.
@@ -0,0 +1,103 @@
//// [tests/cases/compiler/bigintPropertyName.ts] ////
//// [a.ts]
// BigInt cannot be used as an object literal property
{ ({1n: 123}); };
const bigNum: bigint = 0n;
const a = { 1n: 123 };
const b = { [1n]: 456 };
const c = { [bigNum]: 789 };
const arr = [1, 2, 3] as const;
const { 0: d } = arr;
const { "0": e } = arr;
const { 0n: f } = arr; // bigint should give an index error
// BigInt cannot be used as an property name
const x = { 0n: 123 };
//// [g.ts]
interface G {
2n: string;
}
interface H {
"3n": string;
}
class K {
4n = 0;
}
class L {
"5n" = 0;
}
const g : G = { 2n: "propertyNameError2" };
const g2 : G = { "2n": "ok2" };
g[2n];
g2[2n];
const h : H = { 3n: "propertyNameErrorAndMissingProperty3" };
const h2 : H = { "3n": "ok3" };
h[3n];
h2[3n];
const k : K = { 4n: "propertyNameError4" };
const k2 : K = { "4n": "ok4" };
k[4n];
k2[4n];
const l : L = { 5n: "propertyNameErrorAndMissingProperty5" };
const l2 : L = { "5n": "ok4" };
l[5n];
l2[5n];
g.2n; // not valid JS
//// [q.ts]
type Q = 6n | 7n | 8n;
type T = { [t in Q]: string };
//// [a.js]
// BigInt cannot be used as an object literal property
{
({ 1n: 123 });
}
;
const bigNum = 0n;
const a = { 1n: 123 };
const b = { [1n]: 456 };
const c = { [bigNum]: 789 };
const arr = [1, 2, 3];
const { 0: d } = arr;
const { "0": e } = arr;
const { 0n: f } = arr; // bigint should give an index error
// BigInt cannot be used as an property name
const x = { 0n: 123 };
//// [g.js]
class K {
4n = 0;
}
class L {
"5n" = 0;
}
const g = { 2n: "propertyNameError2" };
const g2 = { "2n": "ok2" };
g[2n];
g2[2n];
const h = { 3n: "propertyNameErrorAndMissingProperty3" };
const h2 = { "3n": "ok3" };
h[3n];
h2[3n];
const k = { 4n: "propertyNameError4" };
const k2 = { "4n": "ok4" };
k[4n];
k2[4n];
const l = { 5n: "propertyNameErrorAndMissingProperty5" };
const l2 = { "5n": "ok4" };
l[5n];
l2[5n];
g;
.2n; // not valid JS
//// [q.js]
@@ -0,0 +1,147 @@
//// [tests/cases/compiler/bigintPropertyName.ts] ////
=== a.ts ===
// BigInt cannot be used as an object literal property
{ ({1n: 123}); };
>1n : Symbol(1n, Decl(a.ts, 1, 4))
const bigNum: bigint = 0n;
>bigNum : Symbol(bigNum, Decl(a.ts, 3, 5))
const a = { 1n: 123 };
>a : Symbol(a, Decl(a.ts, 4, 5))
>1n : Symbol(1n, Decl(a.ts, 4, 11))
const b = { [1n]: 456 };
>b : Symbol(b, Decl(a.ts, 5, 5))
>[1n] : Symbol([1n], Decl(a.ts, 5, 11))
const c = { [bigNum]: 789 };
>c : Symbol(c, Decl(a.ts, 6, 5))
>[bigNum] : Symbol([bigNum], Decl(a.ts, 6, 11))
>bigNum : Symbol(bigNum, Decl(a.ts, 3, 5))
const arr = [1, 2, 3] as const;
>arr : Symbol(arr, Decl(a.ts, 8, 5))
>const : Symbol(const)
const { 0: d } = arr;
>d : Symbol(d, Decl(a.ts, 9, 7))
>arr : Symbol(arr, Decl(a.ts, 8, 5))
const { "0": e } = arr;
>e : Symbol(e, Decl(a.ts, 10, 7))
>arr : Symbol(arr, Decl(a.ts, 8, 5))
const { 0n: f } = arr; // bigint should give an index error
>f : Symbol(f, Decl(a.ts, 11, 7))
>arr : Symbol(arr, Decl(a.ts, 8, 5))
// BigInt cannot be used as an property name
const x = { 0n: 123 };
>x : Symbol(x, Decl(a.ts, 14, 5))
>0n : Symbol(0n, Decl(a.ts, 14, 11))
=== g.ts ===
interface G {
>G : Symbol(G, Decl(g.ts, 0, 0))
2n: string;
>2n : Symbol(G[2n], Decl(g.ts, 0, 13))
}
interface H {
>H : Symbol(H, Decl(g.ts, 2, 1))
"3n": string;
>"3n" : Symbol(H["3n"], Decl(g.ts, 3, 13))
}
class K {
>K : Symbol(K, Decl(g.ts, 5, 1))
4n = 0;
>4n : Symbol(K[4n], Decl(g.ts, 6, 9))
}
class L {
>L : Symbol(L, Decl(g.ts, 8, 1))
"5n" = 0;
>"5n" : Symbol(L["5n"], Decl(g.ts, 10, 9))
}
const g : G = { 2n: "propertyNameError2" };
>g : Symbol(g, Decl(g.ts, 14, 5))
>G : Symbol(G, Decl(g.ts, 0, 0))
>2n : Symbol(2n, Decl(g.ts, 14, 15))
const g2 : G = { "2n": "ok2" };
>g2 : Symbol(g2, Decl(g.ts, 15, 5))
>G : Symbol(G, Decl(g.ts, 0, 0))
>"2n" : Symbol("2n", Decl(g.ts, 15, 16))
g[2n];
>g : Symbol(g, Decl(g.ts, 14, 5))
g2[2n];
>g2 : Symbol(g2, Decl(g.ts, 15, 5))
const h : H = { 3n: "propertyNameErrorAndMissingProperty3" };
>h : Symbol(h, Decl(g.ts, 19, 5))
>H : Symbol(H, Decl(g.ts, 2, 1))
>3n : Symbol(3n, Decl(g.ts, 19, 15))
const h2 : H = { "3n": "ok3" };
>h2 : Symbol(h2, Decl(g.ts, 20, 5))
>H : Symbol(H, Decl(g.ts, 2, 1))
>"3n" : Symbol("3n", Decl(g.ts, 20, 16))
h[3n];
>h : Symbol(h, Decl(g.ts, 19, 5))
h2[3n];
>h2 : Symbol(h2, Decl(g.ts, 20, 5))
const k : K = { 4n: "propertyNameError4" };
>k : Symbol(k, Decl(g.ts, 24, 5))
>K : Symbol(K, Decl(g.ts, 5, 1))
>4n : Symbol(4n, Decl(g.ts, 24, 15))
const k2 : K = { "4n": "ok4" };
>k2 : Symbol(k2, Decl(g.ts, 25, 5))
>K : Symbol(K, Decl(g.ts, 5, 1))
>"4n" : Symbol("4n", Decl(g.ts, 25, 16))
k[4n];
>k : Symbol(k, Decl(g.ts, 24, 5))
k2[4n];
>k2 : Symbol(k2, Decl(g.ts, 25, 5))
const l : L = { 5n: "propertyNameErrorAndMissingProperty5" };
>l : Symbol(l, Decl(g.ts, 29, 5))
>L : Symbol(L, Decl(g.ts, 8, 1))
>5n : Symbol(5n, Decl(g.ts, 29, 15))
const l2 : L = { "5n": "ok4" };
>l2 : Symbol(l2, Decl(g.ts, 30, 5))
>L : Symbol(L, Decl(g.ts, 8, 1))
>"5n" : Symbol("5n", Decl(g.ts, 30, 16))
l[5n];
>l : Symbol(l, Decl(g.ts, 29, 5))
l2[5n];
>l2 : Symbol(l2, Decl(g.ts, 30, 5))
g.2n; // not valid JS
>g : Symbol(g, Decl(g.ts, 14, 5))
=== q.ts ===
type Q = 6n | 7n | 8n;
>Q : Symbol(Q, Decl(q.ts, 0, 0))
type T = { [t in Q]: string };
>T : Symbol(T, Decl(q.ts, 0, 22))
>t : Symbol(t, Decl(q.ts, 1, 12))
>Q : Symbol(Q, Decl(q.ts, 0, 0))
@@ -0,0 +1,289 @@
//// [tests/cases/compiler/bigintPropertyName.ts] ////
=== a.ts ===
// BigInt cannot be used as an object literal property
{ ({1n: 123}); };
>({1n: 123}) : {}
> : ^^
>{1n: 123} : {}
> : ^^
>1n : number
> : ^^^^^^
>123 : 123
> : ^^^
const bigNum: bigint = 0n;
>bigNum : bigint
> : ^^^^^^
>0n : 0n
> : ^^
const a = { 1n: 123 };
>a : {}
> : ^^
>{ 1n: 123 } : {}
> : ^^
>1n : number
> : ^^^^^^
>123 : 123
> : ^^^
const b = { [1n]: 456 };
>b : {}
> : ^^
>{ [1n]: 456 } : {}
> : ^^
>[1n] : number
> : ^^^^^^
>1n : 1n
> : ^^
>456 : 456
> : ^^^
const c = { [bigNum]: 789 };
>c : {}
> : ^^
>{ [bigNum]: 789 } : {}
> : ^^
>[bigNum] : number
> : ^^^^^^
>bigNum : bigint
> : ^^^^^^
>789 : 789
> : ^^^
const arr = [1, 2, 3] as const;
>arr : readonly [1, 2, 3]
> : ^^^^^^^^^^^^^^^^^^
>[1, 2, 3] as const : readonly [1, 2, 3]
> : ^^^^^^^^^^^^^^^^^^
>[1, 2, 3] : readonly [1, 2, 3]
> : ^^^^^^^^^^^^^^^^^^
>1 : 1
> : ^
>2 : 2
> : ^
>3 : 3
> : ^
const { 0: d } = arr;
>d : 1
> : ^
>arr : readonly [1, 2, 3]
> : ^^^^^^^^^^^^^^^^^^
const { "0": e } = arr;
>e : 1
> : ^
>arr : readonly [1, 2, 3]
> : ^^^^^^^^^^^^^^^^^^
const { 0n: f } = arr; // bigint should give an index error
>f : any
> : ^^^
>arr : readonly [1, 2, 3]
> : ^^^^^^^^^^^^^^^^^^
// BigInt cannot be used as an property name
const x = { 0n: 123 };
>x : {}
> : ^^
>{ 0n: 123 } : {}
> : ^^
>0n : number
> : ^^^^^^
>123 : 123
> : ^^^
=== g.ts ===
interface G {
2n: string;
>2n : string
> : ^^^^^^
}
interface H {
"3n": string;
>"3n" : string
> : ^^^^^^
}
class K {
>K : K
> : ^
4n = 0;
>4n : number
> : ^^^^^^
>0 : 0
> : ^
}
class L {
>L : L
> : ^
"5n" = 0;
>"5n" : number
> : ^^^^^^
>0 : 0
> : ^
}
const g : G = { 2n: "propertyNameError2" };
>g : G
> : ^
>{ 2n: "propertyNameError2" } : {}
> : ^^
>2n : string
> : ^^^^^^
>"propertyNameError2" : "propertyNameError2"
> : ^^^^^^^^^^^^^^^^^^^^
const g2 : G = { "2n": "ok2" };
>g2 : G
> : ^
>{ "2n": "ok2" } : { "2n": string; }
> : ^^^^^^^^^^^^^^^^^
>"2n" : string
> : ^^^^^^
>"ok2" : "ok2"
> : ^^^^^
g[2n];
>g[2n] : any
> : ^^^
>g : G
> : ^
>2n : 2n
> : ^^
g2[2n];
>g2[2n] : any
> : ^^^
>g2 : G
> : ^
>2n : 2n
> : ^^
const h : H = { 3n: "propertyNameErrorAndMissingProperty3" };
>h : H
> : ^
>{ 3n: "propertyNameErrorAndMissingProperty3" } : {}
> : ^^
>3n : string
> : ^^^^^^
>"propertyNameErrorAndMissingProperty3" : "propertyNameErrorAndMissingProperty3"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const h2 : H = { "3n": "ok3" };
>h2 : H
> : ^
>{ "3n": "ok3" } : { "3n": string; }
> : ^^^^^^^^^^^^^^^^^
>"3n" : string
> : ^^^^^^
>"ok3" : "ok3"
> : ^^^^^
h[3n];
>h[3n] : any
> : ^^^
>h : H
> : ^
>3n : 3n
> : ^^
h2[3n];
>h2[3n] : any
> : ^^^
>h2 : H
> : ^
>3n : 3n
> : ^^
const k : K = { 4n: "propertyNameError4" };
>k : K
> : ^
>{ 4n: "propertyNameError4" } : {}
> : ^^
>4n : string
> : ^^^^^^
>"propertyNameError4" : "propertyNameError4"
> : ^^^^^^^^^^^^^^^^^^^^
const k2 : K = { "4n": "ok4" };
>k2 : K
> : ^
>{ "4n": "ok4" } : { "4n": string; }
> : ^^^^^^^^^^^^^^^^^
>"4n" : string
> : ^^^^^^
>"ok4" : "ok4"
> : ^^^^^
k[4n];
>k[4n] : any
> : ^^^
>k : K
> : ^
>4n : 4n
> : ^^
k2[4n];
>k2[4n] : any
> : ^^^
>k2 : K
> : ^
>4n : 4n
> : ^^
const l : L = { 5n: "propertyNameErrorAndMissingProperty5" };
>l : L
> : ^
>{ 5n: "propertyNameErrorAndMissingProperty5" } : {}
> : ^^
>5n : string
> : ^^^^^^
>"propertyNameErrorAndMissingProperty5" : "propertyNameErrorAndMissingProperty5"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const l2 : L = { "5n": "ok4" };
>l2 : L
> : ^
>{ "5n": "ok4" } : { "5n": string; }
> : ^^^^^^^^^^^^^^^^^
>"5n" : string
> : ^^^^^^
>"ok4" : "ok4"
> : ^^^^^
l[5n];
>l[5n] : any
> : ^^^
>l : L
> : ^
>5n : 5n
> : ^^
l2[5n];
>l2[5n] : any
> : ^^^
>l2 : L
> : ^
>5n : 5n
> : ^^
g.2n; // not valid JS
>g : G
> : ^
>.2n : 0.2
> : ^^^
=== q.ts ===
type Q = 6n | 7n | 8n;
>Q : Q
> : ^
type T = { [t in Q]: string };
>T : T
> : ^
@@ -0,0 +1,22 @@
// @target: esnext
// @module: esnext
// @filename: foo.ts
const foo = 0n;
export { foo as "0n" };
// @filename: correctUse.ts
import { "0n" as foo } from "./foo";
export { foo as "0n" };
// @filename: badImport.ts
import { 0n as foo } from "./foo";
// @filename: badImport2.ts
import { foo as 0n } from "./foo";
// @filename: badExport.ts
export { foo as 0n };
// @filename: badExport2.ts
export { 0n as foo };
+1 -7
View File
@@ -9,6 +9,7 @@ const arr: number[] = [1, 2, 3];
let num: number = arr[1];
num = arr["1"];
num = arr[1n]; // should error
num = [1, 2, 3][1n]; // should error
let key: keyof any; // should be type "string | number | symbol"
key = 123;
@@ -23,10 +24,3 @@ typedArray[bigNum] = 0xAA; // should error
typedArray[String(bigNum)] = 0xAA;
typedArray["1"] = 0xBB;
typedArray[2] = 0xCC;
// {1n: 123} is a syntax error; must go in separate file so BigIntIndex error is shown
// @filename: b.ts
// BigInt cannot be used as an object literal property
const a = {1n: 123};
const b = {[1n]: 456};
const c = {[bigNum]: 789};
@@ -0,0 +1,59 @@
// @target: esnext
// @fileName: a.ts
// BigInt cannot be used as an object literal property
{ ({1n: 123}); };
const bigNum: bigint = 0n;
const a = { 1n: 123 };
const b = { [1n]: 456 };
const c = { [bigNum]: 789 };
const arr = [1, 2, 3] as const;
const { 0: d } = arr;
const { "0": e } = arr;
const { 0n: f } = arr; // bigint should give an index error
// BigInt cannot be used as an property name
const x = { 0n: 123 };
// @filename: g.ts
interface G {
2n: string;
}
interface H {
"3n": string;
}
class K {
4n = 0;
}
class L {
"5n" = 0;
}
const g : G = { 2n: "propertyNameError2" };
const g2 : G = { "2n": "ok2" };
g[2n];
g2[2n];
const h : H = { 3n: "propertyNameErrorAndMissingProperty3" };
const h2 : H = { "3n": "ok3" };
h[3n];
h2[3n];
const k : K = { 4n: "propertyNameError4" };
const k2 : K = { "4n": "ok4" };
k[4n];
k2[4n];
const l : L = { 5n: "propertyNameErrorAndMissingProperty5" };
const l2 : L = { "5n": "ok4" };
l[5n];
l2[5n];
g.2n; // not valid JS
// @filename: q.ts
type Q = 6n | 7n | 8n;
type T = { [t in Q]: string };