• @Select decorator works similarly to the Choice decorator but the function passed as argument directly returns the Primitive instead of declaring the condition.

    The @Select decorator should be used for a small subset of special cases, most of the time the @Choice decorator fits the job perfectly. But sometimes certain format definitions have a long list of sub type you need match to a set of value and defining every available options in the @Choice decorator is verbose.

    At the end of the day use the one you feel make your definition easier to read in your declaration, both are valid options.

    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

    Returns DecoratorType<This, Value>

    The property decorator function.

    In the following example let's imagine the DEFINITION object is actually bigger than it is. The @Select decorator is used to pick the Primitive type of the decorated property with the help of a combination of key found in the Protocol instance.

    class SubProtocol {
    ...
    }

    const DEFINITION = {
    0: {
    1: SubProtocol,
    ...
    0xFF: undefined // Return undefined if shouldn't read anything
    },
    ...
    }

    class Protocol {
    @Uint8
    foo: number

    @Uint8
    bar: number

    @Select(_ => DEFINITION[_.foo][_.bar])
    sub_protocol: any
    }

    A use case where the @Select decorator is mandatory is when working with recursive type definition. Because of the way circular dependencies works in TS you can't reference statically a class that has not already been defined. A workaround to this is to use lazy getter with the @Select decorator.

    class Element {
    @Uint8
    type: number

    @Select(_ => ({
    0x00: () => undefined,
    0x01: () => Protocol,
    0x02: () => PrimitiveSymbol.u8,
    0x03: () => PrimitiveSymbol.u16,
    0x04: () => PrimitiveSymbol.u32,
    }[_.type]()))
    data: any
    }

    class Protocol {
    @Uint32
    length: number

    @Size('length')
    @Relation(Element)
    elements: Element[]
    }