Pesquisa de site

União discriminante do Typescript com propriedade aninhada com uma longa lista de possibilidades


Li em alguns lugares que uniões discriminantes a partir de uma propriedade aninhada não são algo viável neste momento, ou pelo menos não sem funções de guarda, e eu queria saber se há uma maneira de não usar funções de guarda de forma alguma para determinar um tipo.

O objetivo é tentar usar Enums para restringir, porque múltiplos CustomFieldType podem ter o mesmo tipo de value, e seria mais simples registrar casos a cada vez usando uma instrução switch em vez de if-elseif para restringir.

Aqui está um playground de TypeScript que tenta as diferentes possibilidades.

enum CustomFieldType {
    INT = 'int',
    STRING = 'string',
    MULTISELECT = 'multiselect',
    SELECT = 'select'
    // Possibly 20 others
}

interface CustomFieldValueBase<T extends CustomFieldType> {
    customField: {
        type: T;
    }
    value: any;
}

interface CustomFieldValueInt extends CustomFieldValueBase<CustomFieldType.INT> {
    value: number;
}
interface CustomFieldValueString extends CustomFieldValueBase<CustomFieldType.STRING> {
    value: string;
}
interface CustomFieldValueMultiSelect extends CustomFieldValueBase<CustomFieldType.MULTISELECT> {
    value: number[];
}
interface CustomFieldValueSelect extends CustomFieldValueBase<CustomFieldType.SELECT> {
    value: number[];
}

type CustomFieldValue =
  | CustomFieldValueInt
  | CustomFieldValueString
  | CustomFieldValueMultiSelect
  | CustomFieldValueSelect


// Solution wanted
// Won't narrow
function guessType(cfv: CustomFieldValue) {
    switch (cfv.customField.type) {
        case CustomFieldType.INT:
            return cfv.value // should be narrowed to number
        case CustomFieldType.STRING:
            return cfv.value // should be narrowed to string
        case CustomFieldType.MULTISELECT:
        case CustomFieldType.SELECT:
            return cfv.value // should be narrowed to number[]
        default: throw new Error()
    }
}

Artigos relacionados