![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
loadable.ts
Advanced tools
Type-safe loading states for TypeScript
This is a small util library to design type-safe loading states.
It includes:
npm install loadable.ts
yarn add loadable.ts
It introduces a Loadable<T, E>
type that represents three possible states,
Loading
, Success<T>
or Failed<E>
.
type Loadable<T, E = unknown> = Loading | Success<T> | Failed<E>;
Plain TypeScript example:
import { LOADING, success, failed, Loadable } from 'loadable.ts';
function getFoo(): Loadable<Foo> {
if (...) {
return LOADING; // returns a `Loading`
} else if (...) {
return success(...); // returns a `Success<Foo>`
} else {
return failed(...); // returns a `Failed`
}
}
const foo: Loadable<Foo> = getFoo();
if (foo.loading) {
// will infer to `Loading`
console.log('Loading...');
} else if (foo.success) {
// will infer to `Success<Foo>` and provide value object
console.log(`Result: ${foo.value}`);
} else {
// will infer to `Failed` and provide error object
console.error(`Result: ${foo.error}`);
}
To improve semantics and code readability, we provide the following type-guards:
isLoading()
isSuccess()
isFailed()
import { isLoading, isSuccess, Loadable } from 'loadable.ts';
const foo: Loadable<Foo> = getFoo();
if (isLoading(foo)) {
// will infer to `Loading`
console.log('Loading...');
} else if (isSuccess(foo)) {
// will infer to `Success<Foo>` and provide value object
console.log(`Result: ${foo.value}`);
} else {
// will infer to `Failed` and provide error object
console.error(`Result: ${foo.error}`);
}
We provide a mapToLoadable()
operator for RxJS, which can be useful for async streams like HTTP responses.
Observable
with a Loading
stateT
in Observable<T>
to a Success<T>
stateE
in the Observable
to a Failed<E>
stateExample:
function loadFoo(): Observable<Foo> {
// ...
}
const foo$: Observable<Loadable<Foo>> = loadFoo().pipe(mapToLoadable());
// makes use of the provided type-guards
const showSpinner$ = foo$.pipe(map(isLoading));
const showError$ = foo$.pipe(map(isFailed));
const fooValue$ = foo$.pipe(filter(isSuccess), map(it => it.value));
Furthermore, we provide the following additional RxJS operators:
onFailed()
: shorthand for filter(isFailed)
and map((it) => it.error)
onSuccess()
: shorthand for filter(isSuccess)
and map((it) => it.value)
mapSuccess(mapFn)
: allows you to map the value
when it is Success
We also provide three useful structural directives for Angular.
They all accept a Loadable<T>
or Observable<Loadable<T>>
input variable.
*ifLoaded
: it will show the template when the latest value is in Loading
state*ifFailed
: it will show the template when the latest value is in Failed
state*ifSuccess
: it will show the template when the latest value is in Success
stateExample usage:
interface Foo {
name: string;
}
@Component({
/* ... */
})
class MyComponent{
public foo$: Observable<Loadable<Foo>> = ...;
/* ... */
}
<!-- loading state -->
<div class="loading" *ifLoading="foo$"></div>
<!-- failed state -->
<div class="error" *ifFailed="foo$"></div>
<div class="error" *ifFailed="let error of foo$">
{{ error }}
</div>
<!-- success state -->
<div class="result" *ifSuccess="foo$"></div>
<div class="result" *ifSuccess="let foo of foo$">
{{ foo.name }}
</div>
If you want to apply operations to a Loadable
, without the need to unwrap it, you could use the monad()
helper function.
It returns the monadic variant LoadableMonad
which currently provides the following operations:
map(fn: (value: T) => R)
flatMap(fn: (value: T) => Loadable<R>)
Example usage:
interface Foo {
loadableBar: Loadable<Bar>;
}
interface Bar {
name: string;
}
const foo: Loadable<Foo> = ...;
const barName: Loadable<string> = monad(foo)
.flatMap(foo => foo.loadableBar)
.map(bar => bar.name);
// this would be the same as:
const barName = isSuccess(foo) ? isSuccess(foo.value.loadableBar) ? success(foo.value.loadableBar.value.name) : foo.value.loadableBar : foo
Thanks goes to these wonderful people (emoji key):
Dirk Luijk 💻 📖 | Daan Scheerens 🤔 |
This project follows the all-contributors specification. Contributions of any kind welcome!
FAQs
Type-safe loading states for TypeScript
The npm package loadable.ts receives a total of 6 weekly downloads. As such, loadable.ts popularity was classified as not popular.
We found that loadable.ts 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.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.