@@ -870,6 +870,7 @@ import {
870
870
ReverseMappedSymbol,
871
871
ReverseMappedType,
872
872
sameMap,
873
+ sameValueZero,
873
874
SatisfiesExpression,
874
875
ScriptKind,
875
876
ScriptTarget,
@@ -1407,6 +1408,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1407
1408
const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as __String);
1408
1409
const requireSymbol = createSymbol(SymbolFlags.Property, "require" as __String);
1409
1410
1411
+ const InfinitySymbol = createSymbol(SymbolFlags.Property, "Infinity" as __String);
1412
+ InfinitySymbol.declarations = [];
1413
+ const NaNSymbol = createSymbol(SymbolFlags.Property, "NaN" as __String);
1414
+ NaNSymbol.declarations = [];
1415
+
1410
1416
/** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */
1411
1417
let apparentArgumentCount: number | undefined;
1412
1418
@@ -1430,6 +1436,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1430
1436
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
1431
1437
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
1432
1438
isUnknownSymbol: symbol => symbol === unknownSymbol,
1439
+ isInfinitySymbol: symbol => symbol === InfinitySymbol,
1440
+ isNaNSymbol: symbol => symbol === NaNSymbol,
1433
1441
getMergedSymbol,
1434
1442
getDiagnostics,
1435
1443
getGlobalDiagnostics,
@@ -2025,7 +2033,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2025
2033
let deferredGlobalOmitSymbol: Symbol | undefined;
2026
2034
let deferredGlobalAwaitedSymbol: Symbol | undefined;
2027
2035
let deferredGlobalBigIntType: ObjectType | undefined;
2028
- let deferredGlobalNaNSymbol: Symbol | undefined;
2029
2036
let deferredGlobalRecordSymbol: Symbol | undefined;
2030
2037
2031
2038
const allPotentiallyUnusedIdentifiers = new Map<Path, PotentiallyUnusedIdentifier[]>(); // key is file name
@@ -2084,6 +2091,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2084
2091
2085
2092
const builtinGlobals = createSymbolTable();
2086
2093
builtinGlobals.set(undefinedSymbol.escapedName, undefinedSymbol);
2094
+ builtinGlobals.set(InfinitySymbol.escapedName, InfinitySymbol);
2095
+ builtinGlobals.set(NaNSymbol.escapedName, NaNSymbol);
2087
2096
2088
2097
// Extensions suggested for path imports when module resolution is node16 or higher.
2089
2098
// The first element of each tuple is the extension a file has.
@@ -6198,7 +6207,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
6198
6207
if (type.flags & TypeFlags.NumberLiteral) {
6199
6208
const value = (type as NumberLiteralType).value;
6200
6209
context.approximateLength += ("" + value).length;
6201
- return factory.createLiteralTypeNode(value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(-value)) : factory.createNumericLiteral(value));
6210
+ const expression = isInfinityOrNaNString("" + value) ? isNaN(value) ? factory.createToken(SyntaxKind.NaNKeyword) : factory.createToken(SyntaxKind.InfinityKeyword) : factory.createNumericLiteral(Math.abs(value));
6211
+ return factory.createLiteralTypeNode(value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, expression) : expression);
6202
6212
}
6203
6213
if (type.flags & TypeFlags.BigIntLiteral) {
6204
6214
context.approximateLength += (pseudoBigIntToString((type as BigIntLiteralType).value).length) + 1;
@@ -15397,10 +15407,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15397
15407
return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType;
15398
15408
}
15399
15409
15400
- function getGlobalNaNSymbol(): Symbol | undefined {
15401
- return (deferredGlobalNaNSymbol ||= getGlobalValueSymbol("NaN" as __String, /*reportErrors*/ false));
15402
- }
15403
-
15404
15410
function getGlobalRecordSymbol(): Symbol | undefined {
15405
15411
deferredGlobalRecordSymbol ||= getGlobalTypeAliasSymbol("Record" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol;
15406
15412
return deferredGlobalRecordSymbol === unknownSymbol ? undefined : deferredGlobalRecordSymbol;
@@ -19569,15 +19575,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19569
19575
if (s & TypeFlags.NumberLike && t & TypeFlags.Number) return true;
19570
19576
if (s & TypeFlags.NumberLiteral && s & TypeFlags.EnumLiteral &&
19571
19577
t & TypeFlags.NumberLiteral && !(t & TypeFlags.EnumLiteral) &&
19572
- ( source as NumberLiteralType).value === (target as NumberLiteralType).value) return true;
19578
+ sameValueZero(( source as NumberLiteralType).value, (target as NumberLiteralType).value) ) return true;
19573
19579
if (s & TypeFlags.BigIntLike && t & TypeFlags.BigInt) return true;
19574
19580
if (s & TypeFlags.BooleanLike && t & TypeFlags.Boolean) return true;
19575
19581
if (s & TypeFlags.ESSymbolLike && t & TypeFlags.ESSymbol) return true;
19576
19582
if (s & TypeFlags.Enum && t & TypeFlags.Enum && source.symbol.escapedName === target.symbol.escapedName &&
19577
19583
isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true;
19578
19584
if (s & TypeFlags.EnumLiteral && t & TypeFlags.EnumLiteral) {
19579
19585
if (s & TypeFlags.Union && t & TypeFlags.Union && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true;
19580
- if (s & TypeFlags.Literal && t & TypeFlags.Literal && ( source as LiteralType).value === (target as LiteralType).value &&
19586
+ if (s & TypeFlags.Literal && t & TypeFlags.Literal && sameValueZero(( source as LiteralType).value, (target as LiteralType).value) &&
19581
19587
isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true;
19582
19588
}
19583
19589
// In non-strictNullChecks mode, `undefined` and `null` are assignable to anything except `never`.
@@ -19593,7 +19599,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19593
19599
if (s & TypeFlags.Number && (t & TypeFlags.Enum || t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true;
19594
19600
if (s & TypeFlags.NumberLiteral && !(s & TypeFlags.EnumLiteral) && (t & TypeFlags.Enum ||
19595
19601
t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral &&
19596
- ( source as NumberLiteralType).value === (target as NumberLiteralType).value)) return true;
19602
+ sameValueZero(( source as NumberLiteralType).value, (target as NumberLiteralType).value) )) return true;
19597
19603
// Anything is assignable to a union containing undefined, null, and {}
19598
19604
if (isUnknownLikeUnionType(target)) return true;
19599
19605
}
@@ -33554,8 +33560,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
33554
33560
case SyntaxKind.PrefixUnaryExpression:
33555
33561
const op = (node as PrefixUnaryExpression).operator;
33556
33562
const arg = (node as PrefixUnaryExpression).operand;
33557
- return op === SyntaxKind.MinusToken && (arg.kind === SyntaxKind.NumericLiteral || arg.kind === SyntaxKind.BigIntLiteral) ||
33558
- op === SyntaxKind.PlusToken && arg.kind === SyntaxKind.NumericLiteral;
33563
+ return op === SyntaxKind.MinusToken && (arg.kind === SyntaxKind.NumericLiteral || arg.kind === SyntaxKind.BigIntLiteral || isInfinityOrNaNSymbol(arg) ) ||
33564
+ op === SyntaxKind.PlusToken && ( arg.kind === SyntaxKind.NumericLiteral || isInfinityOrNaNSymbol(arg)) ;
33559
33565
case SyntaxKind.PropertyAccessExpression:
33560
33566
case SyntaxKind.ElementAccessExpression:
33561
33567
const expr = (node as PropertyAccessExpression | ElementAccessExpression).expression;
@@ -33565,7 +33571,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
33565
33571
}
33566
33572
return !!(symbol && getAllSymbolFlags(symbol) & SymbolFlags.Enum);
33567
33573
}
33568
- return false;
33574
+ return isInfinityOrNaNSymbol(node);
33575
+ }
33576
+
33577
+ function isInfinityOrNaNSymbol(node: Node): boolean {
33578
+ if (!isIdentifier(node)) {
33579
+ return false;
33580
+ }
33581
+ const symbol = getResolvedSymbol(node);
33582
+ return symbol === InfinitySymbol || symbol === NaNSymbol;
33569
33583
}
33570
33584
33571
33585
function checkAssertionWorker(errNode: Node, type: TypeNode, expression: UnaryExpression | Expression, checkMode?: CheckMode) {
@@ -34825,6 +34839,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34825
34839
base10Value: parsePseudoBigInt((node.operand as BigIntLiteral).text)
34826
34840
}));
34827
34841
}
34842
+ break;
34843
+ case SyntaxKind.InfinityKeyword:
34844
+ switch (node.operator) {
34845
+ case SyntaxKind.MinusToken:
34846
+ return getFreshTypeOfLiteralType(getNumberLiteralType(-Infinity));
34847
+ case SyntaxKind.PlusToken:
34848
+ return getFreshTypeOfLiteralType(getNumberLiteralType(Infinity));
34849
+ }
34850
+ break;
34851
+ case SyntaxKind.NaNKeyword:
34852
+ switch (node.operator) {
34853
+ case SyntaxKind.MinusToken:
34854
+ case SyntaxKind.PlusToken:
34855
+ return getFreshTypeOfLiteralType(getNumberLiteralType(NaN));
34856
+ }
34857
+ break;
34858
+ case SyntaxKind.Identifier:
34859
+ switch (getResolvedSymbol(node.operand as Identifier)) {
34860
+ case InfinitySymbol:
34861
+ switch (node.operator) {
34862
+ case SyntaxKind.MinusToken:
34863
+ return getFreshTypeOfLiteralType(getNumberLiteralType(-Infinity));
34864
+ case SyntaxKind.PlusToken:
34865
+ return getFreshTypeOfLiteralType(getNumberLiteralType(Infinity));
34866
+ }
34867
+ break;
34868
+ case NaNSymbol:
34869
+ switch (node.operator) {
34870
+ case SyntaxKind.MinusToken:
34871
+ case SyntaxKind.PlusToken:
34872
+ return getFreshTypeOfLiteralType(getNumberLiteralType(NaN));
34873
+ }
34874
+ break;
34875
+ }
34828
34876
}
34829
34877
switch (node.operator) {
34830
34878
case SyntaxKind.PlusToken:
@@ -35812,8 +35860,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
35812
35860
}
35813
35861
35814
35862
function checkNaNEquality(errorNode: Node | undefined, operator: SyntaxKind, left: Expression, right: Expression) {
35815
- const isLeftNaN = isGlobalNaN (skipParentheses(left));
35816
- const isRightNaN = isGlobalNaN (skipParentheses(right));
35863
+ const isLeftNaN = isNaNSymbol (skipParentheses(left));
35864
+ const isRightNaN = isNaNSymbol (skipParentheses(right));
35817
35865
if (isLeftNaN || isRightNaN) {
35818
35866
const err = error(errorNode, Diagnostics.This_condition_will_always_return_0,
35819
35867
tokenToString(operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.EqualsEqualsToken ? SyntaxKind.FalseKeyword : SyntaxKind.TrueKeyword));
@@ -35826,12 +35874,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
35826
35874
}
35827
35875
}
35828
35876
35829
- function isGlobalNaN(expr: Expression): boolean {
35830
- if (isIdentifier(expr) && expr.escapedText === "NaN") {
35831
- const globalNaNSymbol = getGlobalNaNSymbol();
35832
- return !!globalNaNSymbol && globalNaNSymbol === getResolvedSymbol(expr);
35833
- }
35834
- return false;
35877
+ function isNaNSymbol(expr: Expression): boolean {
35878
+ return isIdentifier(expr) && getResolvedSymbol(expr) === NaNSymbol;
35835
35879
}
35836
35880
}
35837
35881
@@ -36448,6 +36492,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
36448
36492
negative: false,
36449
36493
base10Value: parsePseudoBigInt((node as BigIntLiteral).text)
36450
36494
}));
36495
+ case SyntaxKind.InfinityKeyword:
36496
+ return getFreshTypeOfLiteralType(getNumberLiteralType(Infinity));
36497
+ case SyntaxKind.NaNKeyword:
36498
+ return getFreshTypeOfLiteralType(getNumberLiteralType(NaN));
36451
36499
case SyntaxKind.TrueKeyword:
36452
36500
return trueType;
36453
36501
case SyntaxKind.FalseKeyword:
@@ -42099,6 +42147,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
42099
42147
return +(expr as NumericLiteral).text;
42100
42148
case SyntaxKind.ParenthesizedExpression:
42101
42149
return evaluate((expr as ParenthesizedExpression).expression, location);
42150
+ case SyntaxKind.InfinityKeyword:
42151
+ return Infinity;
42152
+ case SyntaxKind.NaNKeyword:
42153
+ return NaN;
42102
42154
case SyntaxKind.Identifier:
42103
42155
if (isInfinityOrNaNString((expr as Identifier).escapedText)) {
42104
42156
return +((expr as Identifier).escapedText);
@@ -42854,7 +42906,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
42854
42906
// find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases)
42855
42907
const symbol = resolveName(exportedName, exportedName.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias,
42856
42908
/*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
42857
- if (symbol && (symbol === undefinedSymbol || symbol === globalThisSymbol || symbol.declarations && isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) {
42909
+ if (symbol && (symbol === undefinedSymbol || symbol === InfinitySymbol || symbol === NaNSymbol || symbol === globalThisSymbol || symbol.declarations && isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) {
42858
42910
error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, idText(exportedName));
42859
42911
}
42860
42912
else {
@@ -45205,6 +45257,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
45205
45257
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as __String, /*arity*/ 0, /*reportErrors*/ true);
45206
45258
getSymbolLinks(unknownSymbol).type = errorType;
45207
45259
getSymbolLinks(globalThisSymbol).type = createObjectType(ObjectFlags.Anonymous, globalThisSymbol);
45260
+ getSymbolLinks(InfinitySymbol).type = getFreshTypeOfLiteralType(getNumberLiteralType(Infinity));
45261
+ getSymbolLinks(NaNSymbol).type = getFreshTypeOfLiteralType(getNumberLiteralType(NaN));
45208
45262
45209
45263
// Initialize special types
45210
45264
globalArrayType = getGlobalType("Array" as __String, /*arity*/ 1, /*reportErrors*/ true);
0 commit comments