typocomath/src/numbers/type.ts

45 lines
1.8 KiB
TypeScript

import {ImpType} from '../core/Dispatcher.js'
import type {UnderlyingReal} from '../Complex/type.js'
export const number_type = {
before: ['Complex'],
test: (n: unknown): n is number => typeof n === 'number',
from: {string: s => +s}
}
export interface NumbersReturn<Params> {
// The following description of the return type of `zero` on a single
// number argument has ended up unfortunately rather complicated. However,
// it illustrates the typing is really working: Suppose we have a
// `type Small = 1 | 2 | 3`. Then Small indeed extends number, but we
// can't use the operation `zero(s: Small)` because zero is supposed to
// return something of the same type as its argument, but there is no
// zero in Small. Anyhow, in plain language the below says that given
// one parameter of a subtype of number, as long as that subtype includes 0,
// the zero operation returns a member of the type `0` (so we know even
// at compile time that its value will be 0).
zero: Params extends [infer T]
? T extends number ? 0 extends T ? 0 : never : never
: never
// Note that in any case the simple
// zero: Signature<Params, [number], 0>
// makes complex fail to compile, because it worries that you might be
// making `Complex<Small>` where zero would not return the right type.
one: Params extends [infer T]
? T extends number ? 1 extends T ? 1 : never : never
: never
nan: Params extends [infer T]
? T extends number ? typeof NaN extends T ? typeof NaN : never : never
: never
re: Params extends [infer T]
? T extends number ? UnderlyingReal<T> : never
: never
}
export const zero: ImpType<'zero', [number]> = a => 0
export const one: ImpType<'one', [number]> = a => 1
export const nan: ImpType<'nan', [number]> = a => NaN
export const re: ImpType<'re', [number]> = a => a