Merges two option objects into a new object with superior type inference compared to Object.assign. The key advantage is proper handling of undefined values and optional properties.
import*as
import _
_from'radashi'
const
constdefaults: {
port:number;
host:string;
}
defaults= {
port: number
port: 3000,
host: string
host: 'localhost' }
const
constuserConfig: {
port:number;
ssl:boolean;
}
userConfig= {
port: number
port: 8080,
ssl: boolean
ssl: true }
import _
_.
functionmergeOptions<{
port:number;
host:string;
}, {
port:number;
ssl:boolean;
}>(a: {
port:number;
host:string;
}, b: {
port:number;
ssl:boolean;
}): {
port:number;
ssl:boolean;
host:string;
}
Merges two option objects into a new object.
If both arguments are defined, properties
from the second object (b) will override those
from the first one (a) when keys overlap
If either argument is undefined, the other is returned
If both are undefined, the result is undefined
@param ― a - The first options object, or undefined.
@param ― b - The second options object, or undefined.
@returns ― A merged object when both arguments are defined, otherwise the defined argument, or undefined if both are undefined.
When either argument is undefined, the function returns the other argument with proper typing. When both are undefined, the result is correctly typed as undefined.
import*as
import _
_from'radashi'
// First argument undefined → returns second
import _
_.
functionmergeOptions<undefined, {
b:number;
}>(a:undefined, b: {
b:number;
}): {
b:number;
}
Merges two option objects into a new object.
If both arguments are defined, properties
from the second object (b) will override those
from the first one (a) when keys overlap
If either argument is undefined, the other is returned
If both are undefined, the result is undefined
@param ― a - The first options object, or undefined.
@param ― b - The second options object, or undefined.
@returns ― A merged object when both arguments are defined, otherwise the defined argument, or undefined if both are undefined.
The main advantage of mergeOptions over Object.assign is how it handles optional objects (T | undefined).
With Object.assign, you often have to use workarounds that result in complex intersection types.
import*as
import _
_from'radashi'
type
typeConfig= {
x:number;
y?:string;
} |undefined
Config= {
x: number
x:number;
y?: string
y?:string } |undefined
type
typeOverride= {
y:string;
z:boolean;
} |undefined
Override= {
y: string
y:string;
z: boolean
z:boolean } |undefined
declareconst
constconfig:Config
config:
typeConfig= {
x:number;
y?:string;
} |undefined
Config
declareconst
constoverride:Override
override:
typeOverride= {
y:string;
z:boolean;
} |undefined
Override
// ❌ Using Object.assign with a type assertion forces `config` to be non-nullable,
// but `Config` originally allows `undefined`. This assertion changes the intent,
// and results in a complex intersection type
constbad1=
var Object:ObjectConstructor
Provides functionality common to all JavaScript objects.
Object.
ObjectConstructor.assign<{
x:number;
y?:string;
}, Override>(target: {
x:number;
y?:string;
}, source:Override): {
x:number;
y?:string;
} & {
y:string;
z:boolean;
} (+3overloads)
Copy the values of all of the enumerable own properties from one or more source objects to a
target object. Returns the target object.
@param ― target The target object to copy to.
@param ― source The source object from which to copy properties.
assign(
constconfig:Config
configas
typeNonNullable<T> =T& {}
Exclude null and undefined from T
NonNullable<
typeConfig= {
x:number;
y?:string;
} |undefined
Config>,
constoverride:Override
override)
constbad1: {
x:number;
y?:string;
} & {
y:string;
z:boolean;
}
// Potential runtime error if `config` is undefined.
// ❌ Using Object.assign with an empty object as a workaround is hacky
constbad2=
var Object:ObjectConstructor
Provides functionality common to all JavaScript objects.