Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
type-plus
Advanced tools
Provides additional types and type adjusted utilities for TypeScript.
npm install type-plus
// or
yarn add type-plus
Type assertion is one of the main features of type-plus
.
Type assertions can be immediate
compile time check, or they can have runtime
behavior.
There are 4 kinds of type assertions:
type guard
: User-defined type guard functions (if (isBool(s))
) introduced in TypeScript 1.6.assertion function
: assertion functions (assertIsBool(a)
) introduced in TypeScript 3.7.logical
: functions or generic types that returns true
or false
type to be used in type level programming.filter
: generic type that returns never
if the test fails.Here are the type assertions provided in type-plus
.
Use the one that fits your specific needs.
assertType<T>(subject)
:
✔️ immediate
It ensures subject
satisfies T
.
It is similar to const x: T = subject
without introducing an unused variable.
You need to specify T
for it to work.
assertType<T>(subject, validator)
:
assertType<T>(subject, Class)
:
✔️ assertion function
, runtime
These overloads of assertType
allow you to specify a validator
.
With these overloads, subject
can be unknown
or any
.
If subject
fails the assertion,
a standard TypeError
will be thrown and provide better error info.
For example:
const s: unknown = 1
// TypeError: subject fails to satisfy s => typeof s === 'boolean'
assertType<boolean>(s, s => typeof s === 'boolean')
The message beautification is provided by tersify
.
assertType.isUndefined(subject)
:
assertType.isNull(subject)
:
assertType.isNumber(subject)
:
assertType.isBoolean(subject)
:
assertType.isTrue(subject)
:
assertType.isFalse(subject)
:
assertType.isString(subject)
:
assertType.isFunction(subject)
:
assertType.isConstructor(subject)
:
assertType.isError(subject)
:
✔️ immediate
, assertion function
, runtime
Compiler and runtime assertion with type narrowing from any
.
They assert the type of subject
is that specific type.
i.e. union type will fail at type level:
const s: number | undefined = undefined
assertType.isUndefined(s) // TypeScript complains
They accept any
and will be narrowed to the specific type.
const s: any = undefined
assertType.isUndefined(s)
s // type is undefined
assertType.isNever(subject)
:
✔️ immediate
Check if the subject type is never
.
This function is not very useful in actual code as TypeScript will indicate the error.
But it can be useful when writing tests for types.
This is useful for variables. For type level only check, do the following:
assertType.isTrue(true as Equal<YourType, never>)
assertType.noUndefined(subject)
:
assertType.noNull(subject)
:
assertType.noNumber(subject)
:
assertType.noBoolean(subject)
:
assertType.noTrue(subject)
:
assertType.noFalse(subject)
:
assertType.noString(subject)
:
assertType.noFunction(subject)
:
assertType.noError(subject)
:
✔️ immediate
, runtime
Compiler and runtime assertion.
Assert subject
type does not contain the specific type.
Work against unions.
const s: number | undefined = 1
assertType.noUndefined(s) // TypeScript complains
They accept subject
with type any
or unknown
,
the assertion will happen in runtime to ensure subject
is the specific type.
assertType.as<T>(subject)
:
✔️ immediate
Assert subject
as T
inline.
This is useful to help TypeScript to adjust the type on the fly.
let s: number | undefined = 1
assertType.as<1>(s) // `s` type is now `1`
isType<T>(subject: T)
:
✔️ immediate
It ensures subject
satisfies T
.
It is identical to assertType<T>(subject: T)
.
You need to specify T
.
isType<T>(subject, validator)
:
isType<T>(subject, Class)
:
isType.t<T>(subject?: T)
:
✔️ immediate
, runtime
It can be used as type check: isType.t<Equal<A, B>>()
,
or value type check: isType.t(valueTypeIsTrue)
.
It returns true
when passes (which is the only case when used in TypeScript).
isType.f<T>(subject?: T)
:
✔️ immediate
, runtime
It can be used as type check: isType.f<Equal<A, B>>()
,
or value type check: isType.f(valueTypeIsFalse)
.
It returns true
when passes (which is the only case when used in TypeScript).
isType.equal<true|false, A, B>()
:
✔️ immediate
Slightly easier to use then isType.t<>()
and isType.f<>()
,
when doing type-level only equality comparison as you don't have to import Equal<>
.
✔️ type guard
, runtime
These overloads of isType
allow you to specify a validator
.
With these overloads, subject
can be unknown
or any
.
✔️ immediate
Check is the type never
.
✔️ immediate
Check is the value is type never
.
Equal<A, B>
:
IsEqual<A, B>
:
✔️ logical
Check if A
and B
are the same.
NotEqual<A, B>
:
IsNotEqual<A, B>
:
✔️ logical
Check if A
and B
are not the same.
IsExtend<A, B>
:
IsNotExtend<A, B>
:
✔️ logical
Check if A
extends or not extends B
.
Extendable<A, B>
:
NotExtendable<A, B>
:
✔️ filter
Check if A
extends or not extends B
.
IsAssign<A, B>
:
CanAssign<A, B>
:
✔️ logical
Check if A
can be assigned to B
.
A typical usage is using it with assertType
:
assertType.isFalse(false as CanAssign<boolean, { a: string }>)
assertType.isTrue(true as CanAssign<{ a:string, b:number }, { a: string }>)
canAssign<T>(): (subject) => true
:
✔️ immediate
, logical
Returns a compile-time validating function to ensure subject
is assignable to T
.
const isConfig = canAssign<{ a: string }>()
assertType.isTrue(isConfig({ a: 'a' }))
canAssign<T>(false): (subject) => false
:
✔️ immediate
, logical
Returns a compile-time validating function to ensure subject
is not assignable to T
.
const notA = canAssign<{ a: string }>(false)
assertType.isTrue(notA({ a: 1 }))
notA({ a: '' }) // TypeScript complains
IsNever<T>
:
✔️ logical
Check if A
is never
.
IsNever<never> // true
IsNever<1> // false
type-plus
also provides additional type utilities.
These utilities include utility types and type-adjusted functions.
Note that most predicate
types (such as IsAny<>
) have a Then
and Else
that you can override.
e.g.:
type Yes = IsAny<any, 'yes', 'no'> // 'yes'
type No = IsAny<1, 'yes', 'no'> // 'no'
AnyType<T, Then = T, Else = never>
]: T === any
.IsAny<T, Then = true, Else = false>
]: T === any
(origin: ts-essentials).At<A, N, Fail = never>
: gets the element type at index N
in the array A
.CommonPropKeys<A>
: gets common keys inside the records in the array A
(deprecate CommonKeys
).Concat<A, B>
: [...A, ...B]
.CreateTuple<L, T>
: Creates Tuple<T>
with L
number of elements.drop(array, value)
: drop a particular value from an array.DropFirst<A>
: drops the first value type of A
.DropLast<A>
: drops the last value type of A
.DropMatch<A, Criteria>
: drops entries matching Criteria
in array or tuple A
.DropUndefined<A>
: drop undefined entries from array of tuple A
.Filter<A, Criteria>
: filter the array or tuple A
, keeping entries satisfying Criteria
. Deprecated. Renaming to KeepMatch
FindFirst<A, Criteria>
: gets the first type satisfying Criteria
.FindLast<A, Criteria>
: gets the last type satisfying Criteria
.Head<A>
: gets the first entry in the array.IntersectOfProps<A, K>
: gets the intersect of A[K]
types (deprecate MapToProp
)IsArray<T>
: logical
predicate for Array
.KeepMatch<A, Criteria>
: keeps entries satisfying Criteria
in array or tuple A
.Last<A>
: gets the last type of array or tuple.literalArray(...entries)
: return an array whose items are restricted to the provided literals.PadLeft<A, Total, PadWith>
: pads A
with PadWith
if the length of A
is less than L
.reduceWhile()
: reduce()
with predicate for early termination. ramda
package.Reverse<A>
: reverses the order of A
.Some<A, Criteria>
: true if some elements in A
matches Criteria
.Tail<A>
: Gets the types of a tuple except the first entry.UnionOfProps<A, K>
: gets the union of A[K]
types (deprecate PropUnion
).UnionOfValues<A>
: gets the union of value types in A
(deprecate ArrayValue
).ArrayPlus.IndexAt<A, N, Fail = never>
: gets the normalized index for A
.ArrayPlus.IsIndexOutOfBound<A, N, Then = true, Else = false>
: Is N
an out of bound index of A
. Supports negative numbers.ArrayType<T, Then = N, Else = never>
: Is the type T
exactly an array and not a tuple.KeyTypes
: type of all keys.PrimitiveTypes
: all primitive types, including Function
, symbol
, and bigint
.ComposableTypes
: Types that can contain custom properties. i.e. object
, array
, function
.NonComposableTypes
: Types that cannot contain custom properties. i.e. not composable.JSONPrimitive
: primitive types valid in JSONJSONObject
: JSON objectJSONArray
: JSON arrayJSONTypes
: all JSON compatible types.JSONTypes.get<T>(obj, ...props)
: get a cast value in JSONimport { JSONTypes } from 'type-plus'
const someJson: JSONTypes = { a: { b: ['z', { c: 'miku' }]}}
JSONTypes.get<string>(someJson, 'a', 'b', 1, 'c') // miku
filterKey()
: type adjusted filter by key.findKey()
: type adjusted find by key.forEachKey()
: type adjusted for each by key.HasKey<T, K>
: predicate type checking T
has key K
.hasKey()
: function of HasKey
.IsRecord<T>
: logical
predicate for Record
.KeysWithDiffTypes<A, B>
: gets the keys common in A
and B
but with different value type.mapKey()
: type adjusted map by key.RecordValue<R>
: gets the value type T
from Record<any, T>
video.reduceByKey()
: type adjusted reduce by key.someKey()
: type adjusted some by key.SpreadRecord<A, B>
: type for {...a, ...b}
when both a
and b
are Record
[...A, ...B]
.AwaitedProp<T, V>
: Awaited
on specified props P
in T
.isPromise<R>(subject: any)
: isPromise()
type guard.MaybePromise<T>
: Alias of T | Promise<T>
.PromiseValue<P>
: Gets the type within the Promise.PromiseValueMerge<P1, P2, ...P9>
: Merge the values of multiple promises.mapSeries()
: Similar to bluebird.mapSeries()
but works with async
/await
.transformMaybePromise(value, transformer)
: Apply the transformer
to the value
.MaybePromise.transform()
.ANotB<A, B>
: get object with properties in A
and not in B
, including properties with a different value type.BNotA<A, B>
: flip of ANotB
as<T>(subject)
: assert subject
as T
. Avoid ASI issues such as ;(x as T).abc
asAny(subject)
: assert subject
as any
. Avoid ASI issue such as ;(x as any).abc
EitherAnd<A, B, [C, D]>
: combines 2 to 4 types as A | B | (A & B)
. This is useful for combining options. Deprecated. Renamed to EitherOrBoth
.EitherOrBoth<A, B, [C, D]>
: combines 2 to 4 types as A | B | (A & B)
. This is useful for combining options video.Except<T, K>
: Deprecated. Same as Omit<T, K>
.ExcludePropType<T, U>
: excludes type U
from properties in T
.KeyofOptional<T>
: keyof
that works with Record<any, any> | undefined
.KnownKeys<T>
: extract known (defined) keys from type T
.LeftJoin<A, B>
: left join A
with B
NonNull<T>
: remove null
NonUndefined<T>
: remove undefined
Omit<T, K>
: From T
, pick a set of properties whose keys are not in the union K
. This is the opposite of Pick<T, K>
.OptionalKeys<T>
: gets keys of optional properties in T
.PartialExcept<T, U>
: Deprecated. Same as PartialOmit<T, U>
.PartialOmit<T, U>
: makes the properties not specified in U
becomes optional.PartialPick<T, U>
: makes the properties specified in U
becomes optional.Pick<T, K>
: pick properties K
from T
. Works with unions.RecursivePartial<T>
: make type T
optional recursively.RecursiveRequired<T>
: make type T
required recursively.ReplaceProperty<T, K, V>
: replace property K
in T
with V
.RequiredKeys<T>
: gets keys of required properties in T
.RequiredPick<T, U>
: makes the properties specified in U
become required.RequiredExcept<T, U>
: makes the properties not specified in U
become required.RecursiveIntersect<T, U>
: intersect type U
onto T
recursively.ValueOf<T>
: type of the value of the properties of T
.Widen<T>
: widen literal types.YourType['propName']
.Type predicates are type alias that returns true
or false
.
They can be used to compose complex types.
HasKey<T, K>
: predicate type checking T
has key K
.IsAny<T>
: T === any
(updated to impl: expect-type).IsBoolean<T>
: check for boolean
, but not for true
nor false
.IsDisjoint<A, B>
: is A
and B
is a disjoint set.IsEmptyObject<T>
: is T === {}
.IsLiteral<T>
: is T
a literal type (literal string or number).If<Condition, Then = true, Else = false>
: if statement.And<A, B, Then = true, Else = false>
: logical AND
.Or<A, B, Then = true, Else = false>
: logical OR
.Xor<A, B, Then = true, Else = false>
: logical XOR
.Not<X, Then = true, Else = false>
: logical NOT
.Note that these types work correctly with the boolean
type.
e.g.:
And<boolean, true> -> boolean
Not<boolean> -> boolean
There is a problem with generic distribution: https://github.com/microsoft/TypeScript/issues/41053 So you may encounter some weird behavior if your logic is complex.
Numeric
: either number
or bigint
(origin: type-fest).Zero
: 0
in number
or bigint
(origin: type-fest).Integer<N, Then = N, Else = never>
: is integer (origin: type-fest).Negative<N, Then = N, Else = never>
: is negative (origin: type-fest).NonNegative<N, Then = N, Else = never>
: is non-negative (origin: type-fest)NumberType<T, Then = N, Else = never>
: Is the type T
exactly number
.Abs<N, Fail=never>
: Abs(N)
, Abs<number>
returns Fail
.IsPositive<N>
: is N
a positive number literal. IsPositive<number>
returns false
.IsWhole<N>
: is N
a whole number literal. IsWhole<number>
returns false
.Max<A, B, Fail=never>
: max(A, B)
, for whole number, Fail
otherwise.GreaterThan<A, B, Fail=never>
: A > B
for whole numbers, Fail
otherwise.Add<A, B, Fail=never>
: A + B
for positive and whole numbers, Fail
otherwise.Subtract<A, B, Fail=never>
: A - B
for positive and whole numbers, Fail
otherwise.Increment<A, Fail=never>
: alias of Add<A, 1, Fail>
.Decrement<A, Fail=never>
: alias of Subtract<A, 1, Fail>
.amend(subject)...
: amend subject as union or intersect of T
.facade(subject, ...props)
: create a facade of subject
.getField(subject, key, defaultValue)
: get a field from a subject. Works against nullable and optional subject.hasKey()
: function of HasKey
.hasProperty(value, prop)
: assert value
has property prop
. This will pick the correct union type.isConstructor(subject)
: type guard subject
is a constructor.isSystemError(code, err)
: type guard err
with NodeJS error code.omit(obj, ...props)
: omit properties from obj
.pick(obj, ...props)
: pick properties from obj
.record<K, V>(value?)
: create a Record<K, V>
without extra object prototype.record<R>(value?)
: create a record R
(e.g. { a: number }
) without extra object prototype.required(...)
: merge options and remove Partial<T>
. From unpartial
requiredDeep(...)
: merge options deeply and remove Partial<T>
. From unpartial
split(target, ...splitters)
: split one object into multiple objects.stub<T>(value)
: stub a particular type T
.stub.build<T>(init?)
: build a stub for particular type T
.typeOverrideIncompatible<T>()
: override only the incompatible portion between two types.unpartial()
: merge options and remove Partial<T>
values. From unpartial
type A = {
foo: boolean,
bar: string,
baz: string
}
const overrider = typeOverrideIncompatible<A>()
const source = {
foo: 1,
bar: 'bar',
baz: 'baz'
}
// only the `foo` property is available to override.
overrider(source, { foo: !!source.foo })
The TypeScript type system is structural.
In some cases, we want to express a type with nominal behavior.
type-plus
provides two kinds of nominal types: Brand
and Flavor
.
Brand<B, T>
:
brand(type, subject?)
:
Branded nominal type is the stronger nominal type of the two. It disallows unbranded type assigned to it:
const a = brand('a', { a: 1 })
const b = { a: 1 }
a = b // error
subject
can be any type, from primitive to strings to objects.
brand(type)
:
If you do not provide subject
, brand(type)
will return a brand creator,
so that you can use it to create multiple branded values:
const nike = brand('nike')
const shirt = nike('shirt')
const socks = nike('socks')
Flavor<F, T>
:
flavor(type, subject?)
:
The key difference between Flavor
and Brand
is that
unflavored type can be assigned to Flavor
:
let f = flavor('orange', 'soda')
f = 'mist' // ok
Also, Brand
of the same name can be assigned to Flavor
,
but Flavor
of the same name cannot be assigned to Brand
.
nominalMatch(a, b)
:
nominalMatch()
can be used to compare Brand
or Flavor
.
const b1 = brand('x', 1)
const b2 = brand('y', 1)
nominalMatch(b1, b2) // false
AnyFunction<P, R>
: a generic type for any functionExtractFunction<F>
: extract the function signature from a type F
.extractFunction(fn: F)
: adjust type of fn
to its function signature only.inspect<T>(value: T, inspector?: (v: T) => void)
: inspect a value and return it.console.dir()
ChainFn<T>: T
: chain function that returns the input type.compose(...fns): F
: compose functionscontext()
: a context builder. This is useful to build context for functional programming.AsyncContext
from async-fp.import { context } from 'type-plus'
// { a: 1, b: 2 }
const ctx = context({ a: 1 })
.extend(c => ({ b: c.a + 1 }))
.build()
Some code in this library is created by other people in the TypeScript community. I'm merely adding them in and maybe making some adjustments. Whenever possible, I add attribution to the person who created those codes in the file.
Pipe
.# after fork and clone
npm install
# begin making changes
git checkout -b <branch>
npm run watch
# after making change(s)
git commit -m "<commit message>"
git push
# create PR
FAQs
Provides additional types for TypeScript.
The npm package type-plus receives a total of 17,804 weekly downloads. As such, type-plus popularity was classified as popular.
We found that type-plus demonstrated a healthy version release cadence and project activity because the last version was released less than 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.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.