Core SDK
The SDK Core package provides foundational types essential to the broader SDK ecosystem, primarily serving internal packages. It's designed to ensure consistency and facilitate type safety across the SDK.
Installation
To install this package, you need to have access to the private @sdk
npm scope.
To integrate the SDK Core package into your project, use the following command with your preferred package manager:
npm install @sdk/core
This will add the core functionality required for working with other SDK packages.
Core Types
The Option
Type
The Option
type is inspired by the concept from functional programming languages. It represents a container that might hold a value (Some
) or might not hold any value (None
), effectively encapsulating the presence or absence of a value.
Constructors and Methods:
Option.Value(value)
: Creates anOption
containing a value.Option.None()
: Creates anOption
representing the absence of a value.Option.isSome(option)
: Determines if anOption
contains a value.Option.unwrap(option)
: Extracts the value from anOption
. Throws an error if theOption
isNone
.Option.unwrapOr(option, defaultValue)
: Extracts the value from anOption
, returningdefaultValue
if theOption
isNone
.
Examples:
import { Option } from '@sdk/core';
// Creating an Option with a value
const tokenOption = Option.Value('_AB5YaWdFnulJSC_qFCbX');
console.log(Option.isSome(tokenOption)); // true
console.log(Option.unwrap(tokenOption)); // _AB5YaWdFnulJSC_qFCbX
// Creating an Option without a value
const nothing = Option.None();
console.log(Option.isSome(nothing)); // false
console.log(Option.unwrapOr(nothing, '')); // ""
// Attempting to unwrap a None option will throw an error
try {
console.log(Option.unwrap(nothing)); // This will throw
} catch (error) {
console.error('Error:', error.message);
}
By leveraging the Option
type, developers can more explicitly handle the presence or absence of values, reducing the risk of runtime errors related to undefined or null values. This approach enhances code clarity and reliability, especially in complex applications.
The Result
Type
In the SDK Core package, the Result
type is a powerful abstraction that represents a computation that may either result in a value or an error. This type is inspired by similar constructs in functional programming languages and is designed to enhance error handling and type safety in TypeScript applications.
The Result
type is a generic union type that can contain either a value (Ok
) or an error (Err
), along with a boolean flag (ok
) indicating the state. This design allows for expressive and safe error handling, making it clear when a function's return value needs to be checked for success or failure.
Constructors and Methods
Result.Ok(value)
: Creates aResult
instance representing a successful outcome with a value.Result.Err(error)
: Creates aResult
instance representing a failure outcome with an error.Result.isOk(result)
: Checks if aResult
instance represents a success.Result.isErr(result)
: Checks if aResult
instance represents an error.
Type Parameters
T
: The type of the value contained in a successfulResult
.E
: The type of the error contained in a failedResult
.
Examples
Creating a Successful Result
import { Result } from '@sdk/core';
const successfulResult = Result.Ok(42);
// Result is { ok: true, value: 42 }
console.log(Result.isOk(successfulResult)); // true
console.log(Result.isErr(successfulResult)); // false
Creating a Failed Result
import { Result } from '@sdk/core';
const failedResult = Result.Err('An error occurred');
// Result is { ok: false, error: 'An error occurred' }
console.log(Result.isOk(failedResult)); // false
console.log(Result.isErr(failedResult)); // true
Usage
The Result
type is particularly useful in functions that might fail, allowing the caller to handle success and failure cases explicitly. This pattern encourages checking the result of operations and dealing with errors appropriately, thus avoiding unhandled exceptions and improving application robustness.
Handling Results
Handling a Result
typically involves checking whether it is an Ok
or an Err
and then taking appropriate action.
function processResult(result: Result<number, string>) {
if (Result.isOk(result)) {
console.log(`Success with value: ${result.value}`);
} else {
console.error(`Failed with error: ${result.error}`);
}
}
processResult(successfulResult); // Logs the value
processResult(failedResult); // Logs the error
Leveraging Typed Errors for Enhanced Error Handling
The true power of the Result
type unfolds when the error type E
is defined as a union of possible error types. By specifying a union type for errors, you can precisely control the range of errors that a function can return, enabling more granular error handling and improving the developer's ability to react to different error scenarios.
Advantages of Typed Errors
- Precision: Clearly defines the set of errors that can be expected, making functions easier to use and handle.
- Autocompletion and Type Checking: Takes full advantage of TypeScript's type system, including autocompletion and compile-time type checking for error handling code.
- Documentation: Serves as self-documenting code, indicating to developers what errors to expect and handle.
Example: Typed Errors with Union Types
Consider a scenario where a function can fail due to several distinct errors. By defining these errors as a union type, you can create more descriptive and safer error handling paths.
import { Result } from '@sdk/core';
// Define possible errors as a union type
type NetworkError = { type: 'network'; message: string };
type ValidationError = { type: 'validation'; field: string };
type DatabaseError = { type: 'database'; error: Error };
type MyError = NetworkError | ValidationError | DatabaseError;
// Function that might fail with a specific error
function fetchData(): Result<string, MyError> {
// Example of a failure
return Result.Err({ type: 'network', message: 'Network connection failed' });
}
// Handling the result with typed errors
const result = fetchData();
if (Result.isErr(result)) {
switch (result.error.type) {
case 'network':
console.error(`Network error: ${result.error.message}`);
break;
case 'validation':
console.error(`Validation error on field: ${result.error.field}`);
break;
case 'database':
console.error(`Database error: ${result.error.error.message}`);
break;
default:
console.error('Unknown error occurred');
}
} else {
console.log(`Data fetched successfully: ${result.value}`);
}