45 lines
1.8 KiB
TypeScript
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
|