3 ms·
You can get around it pretty easily: const intSymbol = Symbol('integer') type integer = number & {[intSymbol]: never} const isInteger = (n: unknow
by explaininjs 4y ago
You can get around it pretty easily:
const intSymbol = Symbol('integer')
type integer = number & {[intSymbol]: never}
const isInteger = (n: unknown): n is integer => Number.isInteger(n)
function f(s: string | number) {
if (isInteger(s)) {
const allowed = s.toExponential()
} else {
// s still string | number
}
}
With this you even get to define functions that must accept integers, which is kinda neat.
- benatkin 4y agoThat doesn't seem to address my concern. It seems like more of a curiosity. Whatever floats your boat.
- explaininjs 4y agoHow does it not address your concern? It’s quite literally making isInteger into a type guard. The ‘integer’ type above can passed to any place ‘number’ is needed.
- deleted 4y ago[deleted]
- benatkin 4y agoif (typeof s === 'number' && Number.isInteger(s)) {
- explaininjs 4y agoWhat do you expect me to do with this snippet provided with no context?
- benatkin 4y agoThat's what I was wondering when I saw yours. What I was showing here is that this solution is simpler than yours and just as good. Rather than add a utility function and a faux primitive type, I just do the normal workaround for TypeScript not supporting this, which is to redundantly check that something is both a number and an integer.
- explaininjs 4y agoThe point of having a utility function is that you don't have to do the redundant checks every time you want to make sure it's both a number and an integer. The critical bit is that you need to define a new type for `integer`s distinct from `number`s to allow reusing the code in a way that doesn't break the type system on the negative path, as Ryan and I demonstrated.
- deleted 4y ago[deleted]
- benatkin 4y agoIt isn't redundant in terms of the amount of code written, to me. The overhead of having the utility function and type is greater IMO. If it's in terms of performance, that seems like moving the goalposts. I also wonder if it could be optimized away. Next time I run into it I might use this: if (Number.isInteger(s)) { const allowed = (s as number).toExponential() ...and keep the isInteger check close enough that it's readable. ...or this: if (Number.isInteger(s)) { const n = s as number // should be optimized away by the compiler I think
- explaininjs 4y agoYou asked for isInteger to work as a type guard and I showed you how. If you prefer explicit casts everywhere that's fine, but it isn't a type guard. You could even use the type anonymously if you really want: (n is number & {Symbol(): never}). Whatever floats your boat, as you say.
- benatkin 4y agoOh boy, I never ever asked for a replacement for Number.isInteger! I prefer to use native functions. Have a nice day.
- explaininjs 4y ago