• @Choice decorator match a value to a record of value:primitive.

    The @Choice decorator is just syntactic sugar to the @IfThen decorator, useful for simple straightforward equality comparaison that doesn't requires any preprocessing.

    Type Parameters

    • This extends object

      The type of the class the decorator is applied to.

    • Value

      The type of the decorated property.

    • Args extends string

    Parameters

    • cmp: StringFormattedRecursiveKeyOf<This, Args> | (targetInstance: This) => any

      The name of the property of the target instance containing a value or a function receiving the target instance as parameter that return the value to compare to the record param.

    • match: Record<
          any,
          | undefined
          | Primitive<any>
          | [Primitive<any>, RelationParameters<This, Args>],
      >

      A record where keys are compared against the evaluated cmp value, and values define the corresponding relations.

    • Optionalargs: RelationParameters<This, Args>

      The arguments to pass to the matching relation definition (see Primitive.RelationParameters)

    Returns DecoratorType<This, Value>

    The property decorator function.

    The simplest way to use the @Choice decorator is to reference the name of a property belonging to the target instance to match with the record.

    class Chunk {
    @Uint8
    type: number

    @Choice('type', {
    0x01: PrimitiveSymbol.u8,
    0x02: PrimitiveSymbol.u16,
    0x03: undefined,
    })
    data: number
    }

    class Protocol {
    @While((value: Chunk) => value.type !== 0x03)
    message: Chunk[]
    }

    You can also pass arguments to the relation using comma separeted string. In the following example the value of the property 'length' and 'type' is passed to the constructor of 'Data' on creation. Notice that relation you want to pass arguments requires to be defined inside of an array of two member.

    class Data {
    _length: number
    _type: number

    @Count('_length')
    @Uint8
    data: number[]

    ...

    constructor(length: number, type: number) {
    this._length = length
    this._type = type
    }
    }

    class Header {
    @Count(4)
    @Uint8
    magic: number

    @Uint32
    crc: number
    }

    class Protocol {
    @Uint32
    length: number

    @Uint8
    type: number

    @Choice('type', {
    0x01: Header,
    0x02: [Data, 'length, type'],
    0x03: undefined,
    })
    data: Header | Data | undefined
    }

    An alternative to string reference is to use functions if you need to performs manipulation on the datas.

    class Protocol {
    @Uint32
    length: number

    @Uint8
    type: number

    @Choice(_ => _.type, {
    0x01: Header,
    0x02: [Data, (instance: BinProtocol) => [instance.length - 5, instance.type]],
    0x03: undefined,
    })
    data: number
    }

    You can also define the default arguments you pass to every relations. In the following example the value of the property 'length' will be passed to every relation on creation.

    class Protocol {
    @Uint32
    length: number

    @Uint32
    type: number

    @Choice('type', {
    0x01: Header,
    0x02: Data,
    0x03: undefined,
    }, 'length')
    data: number
    }
    • Use @Choice with the @Else decorator to pass a Primitive by default (see Else)
    class Protocol {
    @Uint8
    something: number

    @Choice('something', {
    0x01: PrimitiveSymbol.u8
    })
    @Else(PrimitiveSymbol.u16)
    data: number
    }
    • If you are working with recursive types definition you should use the @Select decorator instead (for more informations see Select).