-
Notifications
You must be signed in to change notification settings - Fork 13k
Closed
Labels
CommittedThe team has roadmapped this issueThe team has roadmapped this issueExperience EnhancementNoncontroversial enhancementsNoncontroversial enhancementsFixedA PR has been merged for this issueA PR has been merged for this issueSuggestionAn idea for TypeScriptAn idea for TypeScript
Milestone
Description
Suggestion
π Search Terms
disallow NaN
comparing with NaN
disallow comparing NaN
β Viability Checklist
My suggestion meets these guidelines:
- [?] This wouldn't be a breaking change in existing TypeScript/JavaScript code
- β This wouldn't change the runtime behavior of existing JavaScript code
- β This could be implemented without emitting different JS based on the types of the expressions
- β This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- β This feature would agree with the rest of TypeScript's Design Goals.
β Suggestion
Similar to #45978 . So the error should be something like The condition will always return 'false' since NaN !== NaN. Use Number.isNaN.
π Motivating Example
function setReputation (n: number)
{
// ! here is the bug:
if (n === NaN) throw new Error('setReputation:: Impossible reputation')
// update the record in a remote DB
}
const foundGolems = 0
const killedGolems = 0
setReputation(killedGolems / foundGolems * 100)
// 0/0 is NaN
or what has actually happened to me:
export function clamp ( // @license CC0
n: number,
min: number|bigint,
max: number|bigint,
): typeof n
export function clamp (
n: bigint,
min: number|bigint,
max: number|bigint,
): typeof n
export function clamp (
n: number|bigint,
min: number|bigint,
max: number|bigint,
): typeof n
{
// +null === 0
// +'' === 0
// +undefined === NaN
const nFixed = typeof n === 'bigint' ? n : (
// @ts-ignore
'' === n || n === null || typeof n === 'symbol'
? NaN : +n
)
const minFixed = typeof min === 'bigint' ? min : (
// @ts-ignore
'' === min || min === null || typeof min === 'symbol'
? NaN : +min
)
const maxFixed = typeof max === 'bigint' ? max : (
// @ts-ignore
'' === max || max === null || typeof max === 'symbol'
? NaN : +max
)
if (nFixed === NaN)
{
const ret = nFixed
//const ret = min == max ? (typeof min === 'bigint' ? +min.toString() : min) : nFixed
console.warn(
'clamp(n=%O, min=%O, max=%O):: n === NaN; returning %O',
n, min, max, ret,
)
return ret
}
let ret: typeof n
if (
minFixed === NaN
&&
maxFixed === NaN
)
{
ret = nFixed
console.warn(
'clamp(n=%O, min=%O, max=%O):: min === NaN && max === NaN; returning `n` (%O)',
n, min, max, ret,
)
}
else if (maxFixed < minFixed)
{
// throw new RangeError
//ret = maxFixed // similar to torch.clamp
ret = minFixed // because arguments are specified in the left-to-right *order*.
//ret = nFixed < maxFixed ? maxFixed : (nFixed > minFixed ? minFixed : nFixed)
/*console.warn(
'clamp(n=%O, min=%O, max=%O):: max<min; returning `min` (%O)',
n, min, max, ret
)*/
}
else
{
ret = nFixed < minFixed ? minFixed : (nFixed > maxFixed ? maxFixed : nFixed)
}
if (typeof n === 'bigint')
{
return typeof ret === 'bigint' ? ret : BigInt(Math.floor(ret))
}
if (typeof ret === 'bigint')
{
return +ret.toString()
}
return ret
}
π» Use Cases
Since NaN is very rare, a programmer could forget to use Number.isNaN(variable)
, and accidentally use ===
.
Or a programmer could have never even learned this, and just applies knowledge from other langs where NaN === NaN.
fatcerberus, Josh-Cena, nicolas377, MilesBHuff, bakkot and 2 morea-tarasyuk
Metadata
Metadata
Assignees
Labels
CommittedThe team has roadmapped this issueThe team has roadmapped this issueExperience EnhancementNoncontroversial enhancementsNoncontroversial enhancementsFixedA PR has been merged for this issueA PR has been merged for this issueSuggestionAn idea for TypeScriptAn idea for TypeScript