Welcome to @safelytyped/ip-port
!
- Introduction
- IpPort
- makeIpPort()
- resolveIpPortToNumber()
- resolveIpPortToString()
- isIpPort()
- mustBeIpPort()
- validateIpPortData()
A safe type is a type that can only ever hold legal values.
For example, IpPort
is a safe type, because it can only ever represent an IP port number in the range 0-65535.
If your function accepts a safe type, your function doesn't need to do its own defensive programming for robustness.
Safe types do the defensive programming for you.
On top of that, we build our safe types using written coding standards.
If you need to limit which IP port numbers are valid, don't start adding defensive programming to your code. Instead, create a refined type that's based on IpPort
.
For example, here's the code for a well-known IP port type (ports starting at 1024
):
import {
DEFAULT_DATA_PATH,
THROW_THE_ERROR,
TypeGuaranteeOptions
} from "@safelytyped/core-types";
import {
IpPort,
isIpPort,
makeIpPort,
mustBeIpPort
} from "@safelytyped/ip-port";
// to refine a branded type, we have to manually brand it
// it'll still turn into a string or number at runtime
export type WellKnownIpPort = IpPort & {
"your-package/well-known-ip-port": "your-package/well-known-ip-port"
}
export const makeWellKnownIpPort = (
input: unknown,
{
onError = THROW_THE_ERROR,
path = DEFAULT_DATA_PATH
}: Partial<TypeGuaranteeOptions> = {}
): WellKnownIpPort => makeIpPort(input, { onError, path, minInc: 1024 }) as WellKnownIpPort;
export const isWellKnownIpPort = (
input: unknown
) => isIpPort(input, { minInc: 1024 });
export const mustBeWellKnownIpPort = (
input: unknown,
{
onError = THROW_THE_ERROR,
path = DEFAULT_DATA_PATH
}: Partial<TypeGuaranteeOptions> = {}
): WellKnownIpPort => mustBeIpPort(input, { onError, path, minInc: 1024 }) as WellKnownIpPort;
You can use it everywhere that accepts an IpPort
, but it'll only ever hold values in the range 1024-65535.
We're building a library of safe types over on GitHub.
You can also search the NPM public repositories for the keyword "safe type".
/**
* `IpPort` represents the port number of an IP address.
*
* @category IpPort
*/
export type IpPort = Branded<string|number, "@safelytyped/ip-port/ip-port">;
IpPort
is an option type. It can be either a string
or a number
- we support either.
The type is branded, to help the compiler catch mistakes. At runtime, it turns into a plain string
or number
.
Use makeIpPort()
to create a safe IpPort
value.
/**
* `makeIpPort()` is a smart constructor. Use it to create an {@link IpPort}
* type from a `string` or `number`.
*
* @param input
* The number of the port you want to use.
* @param onError
* If `input` fails validation, we'll call your `onError` handler with an
* {@link AppError} to explain why.
* @param path
* Where are you in the nested data structure you are creating?
* @param minInc
* The lowest number IP port that's acceptable. Defaults to
* {@link MIN_IP_PORT}. Override this if you are creating a refined type.
* @param maxInc
* The highest number IP port that's acceptable. Defaults to
* {@link MAX_IP_PORT}. Override this if you are creating a refined type.
* @returns
* - `input` converted to an `IpPort`
*
* @category IpPort
*/
export function makeIpPort = (
input: unknown,
{
onError = THROW_THE_ERROR,
path = DEFAULT_DATA_PATH,
minInc = MIN_IP_PORT,
maxInc = MAX_IP_PORT,
}: Partial<MakeNominalTypeOptions> & Partial<ValidateIpPortDataOptions> = {}
): IpPort;
makeIpPort()
turns your string
or number
into an IpPort
type. It verifies that your input
is a valid IP port number.
/**
* `resolveIpPortToNumber() converts an {@link IpPort} option type
* to be a valid integer number.
*
* @category IpPort
*/
export function resolveIpPortToNumber(input: IpPort): number;
Use resolveIpPortToNumber()
to turn your IpPort
into a number
- even if it's actually a string
in the option type.
/**
* `resolveIpPortToString()` converts an {@link IpPort} option type
* to be a valid string.
*
* @category IpPort
*/
export function resolveIpPortToString(input: IpPort): string;
Use resolveIpPortToString()
to turn your IpPort
into a string
- even if it's actually a number
in the option type.
/**
* `isIpPort()` is a type guard. Use it to prove that the given `input`
* can be safely used as a {@link IpPort}.
*
* @param input
* the value to examime
* @param minInc
* The lowest number IP port that's acceptable. Defaults to
* {@link MIN_IP_PORT}. Override this if you are creating a refined type.
* @param maxInc
* The highest number IP port that's acceptable. Defaults to
* {@link MAX_IP_PORT}. Override this if you are creating a refined type.
*
* @category IpPort
*/
export function isIpPort(
input: unknown,
{
minInc = MIN_IP_PORT,
maxInc = MAX_IP_PORT
}: Partial<ValidateIpPortDataOptions> = {}
): input is IpPort;
Use isIpPort()
when you need to convince the TypeScript compiler that your value is, indeed, an IpPort
.
/**
* `mustBeIpPort()` is a type guarantee. Use it to guarantee that the
* given `input` can be safely used as a {@link IpPort}.
*
* @param input
* The value to examine
* @param onError
* If `input` fails validation, we'll call your `onError` handler with an
* {@link AppError} to explain why.
* @param path
* Where are you in the nested data structure you are creating?
* @param minInc
* The lowest number IP port that's acceptable. Defaults to
* {@link MIN_IP_PORT}. Override this if you are creating a refined type.
* @param maxInc
* The highest number IP port that's acceptable. Defaults to
* {@link MAX_IP_PORT}. Override this if you are creating a refined type.
*
* @category IpPort
*/
export function mustBeIpPort(
input: unknown,
{
onError = THROW_THE_ERROR,
path = DEFAULT_DATA_PATH,
minInc = MIN_IP_PORT,
maxInc = MAX_IP_PORT,
}: Partial<TypeGuaranteeOptions> & Partial<ValidateIpPortDataOptions> = {}
): IpPort;
Use mustBeIpPort()
when you need to make sure that you've got an IpPort
. It throws an error if you haven't, so you don't need to check the return value.
/**
* `validateIpPortData()` is a data validator. Use it to prove that your
* input value can be used as an IP port.
*
* @param path
* where are you in the nested data structure that you're validating?
* Use {@link DEFAULT_DATA_PATH} if you're not in a nested data structure.
* @param input
* The value to validate.
* @param minInc
* The lowest number IP port that's acceptable. Defaults to
* {@link MIN_IP_PORT}. Override this if you are creating a refined type.
* @param maxInc
* The highest number IP port that's acceptable. Defaults to
* {@link MAX_IP_PORT}. Override this if you are creating a refined type.
* @returns
* - `input`, type-cast to be an {@link IpPort}, on success, or
* - an AppError explaining why validation failed
*
* @category IpPort
*/
export function validateIpPortData(
path: DataPath,
input: number | string | unknown,
{
minInc = MIN_IP_PORT,
maxInc = MAX_IP_PORT
}: Partial<ValidateIpPortDataOptions> = {}
): AppErrorOr<IpPort>;
This is the validator that isIpPort()
, makeIpPort()
and mustBeIpPort()
all use.