Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
typed-assert
Advanced tools
typed-assert
typed-assert
is a typesafe assertion library implementing the TS 3.7 Assertion Functions API, without external dependencies.
See the documentation.
zod
While this library does a fine job for most simple use cases, please consider using zod
if you need more complex assertions.
npm install typed-assert
or
yarn add typed-assert
typed-assert
promotes using unknown
instead of any
for "untrusted" values, e.g. user input, while still benefiting from incremental typing.
For example, JSON.stringify
returns any
, which is not typesafe. With typed-assert
, we can instead treat the result as unknown
and gradually check the contents at runtime and still get correct type inference:
import * as t from "typed-assert";
const parseConfigFile = (file: string): { readonly a: string, readonly b: number } => {
const contents = JSON.parse(fs.readFileSync(file, { encoding: 'utf8'})) as unknown;
// contents is "unknown" instead of any, because we don't trust the input yet
t.isRecord(contents);
// contents is "Record<string, unknown>"
t.isString(contents.a);
// contents.a is "string"
t.isNumber(contents.b):
// contents.b is "number";
return {
a: contents.a,
b: contents.b,
}; // correctly typed
}
typed-assert
is both a compile-time and runtime assert library. It leverages the assertion function
feature of TypeScript to help the typechecker narrow the inferred types. In many cases, this significantly reduces the need to use any
, and promotes using unknown
instead.
For example:
const u: unknown = {
a: "value",
b: 12,
};
chai.assert.typeOf(u, "object");
// u is still "unknown"
chai.assert.isNotNull(u);
// u is still "unknown"
chai.assert.typeof(u.a, "string");
// TS Error (ts2571): u is "unknown"
import * as t from "typed-assert";
t.isRecord(u);
// u is Record<string, unknown>
t.isString(u.a);
// u.a is string
t.isNumber(u.b);
// u.b is number
const v: { a: string; b: number } = u;
// no need to us `as ...`
typed-assert
comes with a set of common assertions, as well as assertion combinators and utilities.
See the documentation for a full reference.
import * as t from "typed-assert";
// Base asserts
t.isExactly("a", "a");
t.isNotUndefined(null);
t.isNotNull(undefined);
// Asserts combinators
t.isOneOf("b", ["a", "b", "c"]);
t.isArrayOf([2, 3, 4], t.isNumber);
// Custom composite checks
interface ICustomType {
readonly a: {
readonly b: "c";
readonly d: string;
};
readonly f?: number;
}
function assertCustomType(input: unknown): asserts input is ICustomType {
t.isRecordWithKeys(input, ["a", "f"]);
t.isRecordWithKeys(input.a, ["b", "d"]);
t.isExactly(input.a.b, "c");
t.isString(input.a.d);
t.isOption(input.f, t.isNumber);
}
const v = {
a: {
b: "c",
d: "",
},
};
assertCustomType(v);
This library also comes with a combinator to transform an assertion functions into a type guard function:
const checkNumber = t.check(t.isNumber);
checkNumber(1) === true;
checkNumber("") === false;
It is especially convenient when combined with functional operations such as Array#filter
:
const t = ["a", 3, "c", 4, null, 2]
.filter(t.check(t.isNumber))
.map(x => x % 2 === 0 ? x : null) // x: number
.filter(t.check(t.isNotNull));
// t: number[] = [4, 2]
To encourage using asserts when dealing with untrusted JSON input, the following function is also exported:
export const safeJsonParse = (json: string): unknown =>
JSON.parse(json) as unknown;
This library is designed to work in the browser as well as in Node without external dependencies, and by default does not use the assert
module from the Node stdlib, so it ships with a very basic assert
implementation:
export type WeakAssert = (input: unknown, message?: string) => void;
export const defaultAssert: WeakAssert = (condition, message) => {
if (!condition) {
throw new TypeError(message);
}
};
It is however possible to configure the library to use a provided base assert
function, such as the native assert
module:
import * as t from "typed-assert";
import nodeAssert from "assert";
t.setBaseAssert(nodeAssert);
Due to limitations in the typechecker, there are syntactic restrictions in how to define and use type assertion functions. For example, you can not dynamically define an assertion function, even if it looks like a static definition.
Thus the following code won't compile:
function createIsExactly<T>(value: T): (input: unknown) => asserts input is T {
return function isExactly(input: unknown): asserts input is T {
t.isExactly(input, value);
};
}
// No problem so far
createIsExactly("a")(null);
// Won't compile:
// Assertions require the call target to be an
// identifier or qualified name.ts(2776)
For similar reasons, it is not possible to use type-inferred arrow functions to define assertion functions:
const isExactlyNull = (input: unknown): asserts input is null => assert(input === value);
// No problem so far
isExactlyNull("a", null):
// Won't compile:
// Assertions require the call target to be an
// identifier or qualified name.ts(2776)
It is however possible to use arrow function with explicit typing of the left-hand operand:
const isExactlyNull: (input: unknown) => asserts input is null = (input) =>
assert(input === null);
isExactlyNull("a");
// No problem
To simplify the implementation,
To simplify this pattern, this library also exports the Assert<Input, Output>
type as defined below:
export type Assert<T> = (
input: unknown,
message?: string,
) => asserts input is T;
const isExactlyNull: Assert<null> = (input) => assert(input === null);
isExactlyNull("a");
// No problem
For convenience, this library also exports the following types, used internally:
export type WeakAssert = (input: unknown, message?: string) => void;
export type SubType<Input, Output> = Output extends Input ? Output : never;
export type Assert<Input = unknown, Output = Input> = (
input: Input,
message?: string,
) => asserts input is SubType<Input, Output>;
export type Check<Input = unknown, Output = Input> = (
input: Input,
) => input is SubType<Input, Output>;
This way we can write:
const isExactlyNull: Assert<unknown, null> = (input) =>
assert(input === null);
isExactlyNull("a");
FAQs
typesafe assertion library for TypeScript 3.7+
The npm package typed-assert receives a total of 3,012,233 weekly downloads. As such, typed-assert popularity was classified as popular.
We found that typed-assert demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.