Add Option.unwrapOrDefault (#1942)
* Add Option.unwrapOrDefault * linting * metadata createType(registry, ...) -> registry.createType(...) * Linting * Cleanup tests
This commit is contained in:
@@ -49,7 +49,7 @@ describe('Option', (): void => {
|
||||
// Option<Option<Bytes>> (hence the length, since it is from storage)
|
||||
const HEX = '0x210100000000000000000000000000000000000000000000000000000000000000000000000000000000011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce';
|
||||
|
||||
// whatc the hex prefix and length
|
||||
// watch the hex prefix and length
|
||||
expect(
|
||||
new Option(registry, Bytes, HEX).toHex().substr(6)
|
||||
).toEqual(HEX.substr(2));
|
||||
@@ -59,7 +59,7 @@ describe('Option', (): void => {
|
||||
const HEX = '0x12345678';
|
||||
|
||||
expect(
|
||||
(new Option(registry, U32, HEX).unwrap() as U32).toNumber()
|
||||
new Option(registry, U32, HEX).unwrap().toNumber()
|
||||
).toEqual(0x12345678);
|
||||
});
|
||||
|
||||
@@ -97,22 +97,30 @@ describe('Option', (): void => {
|
||||
});
|
||||
|
||||
describe('utils', (): void => {
|
||||
const testeq = new Option(registry, Text, '1234');
|
||||
const test = new Option(registry, Text, '1234');
|
||||
|
||||
it('compares against other option', (): void => {
|
||||
expect(testeq.eq(new Option(registry, Text, '1234'))).toBe(true);
|
||||
expect(test.eq(new Option(registry, Text, '1234'))).toBe(true);
|
||||
});
|
||||
|
||||
it('compares against raw value', (): void => {
|
||||
expect(testeq.eq('1234')).toBe(true);
|
||||
expect(test.eq('1234')).toBe(true);
|
||||
});
|
||||
|
||||
it('unwraps to default if empty', (): void => {
|
||||
expect(new Option(registry, Text).unwrapOr('6789')).toBe('6789');
|
||||
it('unwrapOr to specified if empty', (): void => {
|
||||
expect(new Option(registry, Text).unwrapOr('6789').toString()).toEqual('6789');
|
||||
});
|
||||
|
||||
it('unwraps to value if non-empty', (): void => {
|
||||
expect((new Option(registry, Text, '1234').unwrapOr(null) as Text).toString()).toBe('1234');
|
||||
it('unwrapOr to specified if non-empty', (): void => {
|
||||
expect(new Option(registry, Text, '1234').unwrapOr(null)?.toString()).toEqual('1234');
|
||||
});
|
||||
|
||||
it('unwrapOrDefault to default if empty', (): void => {
|
||||
expect(new Option(registry, U32).unwrapOrDefault().toNumber()).toEqual(0);
|
||||
});
|
||||
|
||||
it('unwrapOrDefault to specified if non-empty', (): void => {
|
||||
expect(new Option(registry, U32, '1234').unwrapOrDefault().toNumber()).toEqual(1234);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,6 +10,32 @@ import Null from '../primitive/Null';
|
||||
import { typeToConstructor } from './utils';
|
||||
import Base from './Base';
|
||||
|
||||
/** @internal */
|
||||
function decodeOptionU8a (registry: Registry, Type: Constructor, value: Uint8Array): Codec {
|
||||
return !value.length || value[0] === 0
|
||||
? new Null(registry)
|
||||
: new Type(registry, value.subarray(1));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function decodeOption (registry: Registry, Type: Constructor, value?: any): Codec {
|
||||
if (isNull(value) || isUndefined(value) || value instanceof Null) {
|
||||
return new Null(registry);
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
} else if (value instanceof Option) {
|
||||
return decodeOption(registry, Type, value.value);
|
||||
} else if (value instanceof Type) {
|
||||
// don't re-create, use as it (which also caters for derived types)
|
||||
return value;
|
||||
} else if (isU8a(value)) {
|
||||
// the isU8a check happens last in the if-tree - since the wrapped value
|
||||
// may be an instance of it, so Type and Option checks go in first
|
||||
return decodeOptionU8a(registry, Type, value);
|
||||
}
|
||||
|
||||
return new Type(registry, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Option
|
||||
* @description
|
||||
@@ -19,42 +45,17 @@ import Base from './Base';
|
||||
* with a value if/as required/found.
|
||||
*/
|
||||
export default class Option<T extends Codec> extends Base<T> {
|
||||
private _Type: Constructor;
|
||||
private _Type: Constructor<T>;
|
||||
|
||||
constructor (registry: Registry, Type: Constructor | keyof InterfaceTypes, value?: any) {
|
||||
constructor (registry: Registry, Type: Constructor<T> | keyof InterfaceTypes, value?: any) {
|
||||
const Clazz = typeToConstructor(registry, Type);
|
||||
|
||||
super(registry, Option.decodeOption(registry, Clazz, value));
|
||||
super(registry, decodeOption(registry, Clazz, value));
|
||||
|
||||
this._Type = Clazz;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
public static decodeOption (registry: Registry, Type: Constructor, value?: any): Codec {
|
||||
if (isNull(value) || isUndefined(value) || value instanceof Null) {
|
||||
return new Null(registry);
|
||||
} else if (value instanceof Option) {
|
||||
return Option.decodeOption(registry, Type, value.value);
|
||||
} else if (value instanceof Type) {
|
||||
// don't re-create, use as it (which also caters for derived types)
|
||||
return value;
|
||||
} else if (isU8a(value)) {
|
||||
// the isU8a check happens last in the if-tree - since the wrapped value
|
||||
// may be an instance of it, so Type and Option checks go in first
|
||||
return Option.decodeOptionU8a(registry, Type, value);
|
||||
}
|
||||
|
||||
return new Type(registry, value);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
private static decodeOptionU8a (registry: Registry, Type: Constructor, value: Uint8Array): Codec {
|
||||
return !value.length || value[0] === 0
|
||||
? new Null(registry)
|
||||
: new Type(registry, value.subarray(1));
|
||||
}
|
||||
|
||||
public static with<O extends Codec> (Type: Constructor | keyof InterfaceTypes): Constructor<Option<O>> {
|
||||
public static with<O extends Codec> (Type: Constructor<O> | keyof InterfaceTypes): Constructor<Option<O>> {
|
||||
return class extends Option<O> {
|
||||
constructor (registry: Registry, value?: any) {
|
||||
super(registry, Type, value);
|
||||
@@ -170,4 +171,14 @@ export default class Option<T extends Codec> extends Base<T> {
|
||||
? this.unwrap()
|
||||
: defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the value that the Option represents (if available) or defaultValue if none
|
||||
* @param defaultValue The value to return if the option isNone
|
||||
*/
|
||||
public unwrapOrDefault (): T {
|
||||
return this.isSome
|
||||
? this.unwrap()
|
||||
: new this._Type(this.registry);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user