Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

128
Visualizações
Casting types in a switch

I am trying to modularize my type casting. This is my code:

export enum detailsDataTypes {
  MACHINE = 'MACHINE',
  USER = 'USER',
  ABSTRACT = 'ABSTRACT',
}

export type sharedTypes = {
  name?: string;
  OEECategory?: string;
  OAECategory?: string;
  color?: string;
  type?: detailsDataTypes;
};

export type AbstractData = sharedTypes & {
  layer: string;
};

export type UserData = sharedTypes & {
  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
};

export type MachineData = sharedTypes & {
  stateCategory: string;
  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
  canOverrideOnlyByStates: boolean;
};

type DetailsData = AbstractData | UserData | MachineData;

export const detailsDataCaster = (data: DetailsData): DetailsData | null => {
  switch (data.type) {
    case detailsDataTypes.ABSTRACT:
      return <AbstractData>data;
    case detailsDataTypes.MACHINE:
      return <MachineData>data;
    case detailsDataTypes.USER:
      return <UserData>data;
    default:
      console.log('Wrong data type. Go yell at backend team or check your mocks');
      return null;
  }
};

What I'm trying to achieve, is tell TS that I'm returning AbstractData OR UserData OR MachineData OR null. But now, it doesn't like me doing this:

export const Details: FC<IDetails> = ({ data: $data = mockUserData }): ReactElement => {
  const data = detailsDataCaster($data);
  switch (data.type) {
    case detailsDataTypes.ABSTRACT:
      return <>Abstract</>;
    case detailsDataTypes.MACHINE:
      return <>Machine</>;
    case detailsDataTypes.USER:
      return <UserDisplay data={data} />; // error is here
    default:
      return <div />;
  }
};

Error

Type 'DetailsData' is not assignable to type 'UserData'.
  Type 'AbstractData' is not assignable to type 'UserData'.
    Type 'AbstractData' is missing the following properties from type '{ timeout: number; stateAfterTimeout: string; accessCanChoose: string; accessCanOverride: string; }': timeout, stateAfterTimeout, accessCanChoose, accessCanOverride

As I understand | does not mean OR in TS. I know there is the AND &, but this would make no sense. I thought that if I cast, it would be clear as to what I'm returning, but I see it's not so simple. What am I missing?

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

If every type extending the sahredTypes would specify its own type the switch will magically work:

export enum detailsDataTypes {
  MACHINE = 'MACHINE',
  USER = 'USER',
  ABSTRACT = 'ABSTRACT',
}

export interface sharedTypes {
  name?: string;
  OEECategory?: string;
  OAECategory?: string;
  color?: string;
  type?: detailsDataTypes;
};

export interface AbstractData extends sharedTypes {
  type: detailsDataTypes.ABSTRACT;

  layer: string;
};

export interface UserData extends sharedTypes {
  type: detailsDataTypes.USER;

  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
};

export interface MachineData extends sharedTypes {
  type: detailsDataTypes.MACHINE;

  stateCategory: string;
  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
  canOverrideOnlyByStates: boolean;
};

type DetailsData = AbstractData | UserData | MachineData;

Playgound link that shows the type is correctly inferred from the switch.

about 4 years ago · Juan Pablo Isaza Relatório

0

You might want to add a discriminant value to each type like this...

export type AbstractData = sharedTypes & {
  layer: string;
  type: detailsDataTypes.ABSTRACT; // add this field, it can only be of this literal value
};

export type UserData = sharedTypes & {
  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
  type: detailsDataTypes.USER; // add this field
};

export type MachineData = sharedTypes & {
  stateCategory: string;
  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
  canOverrideOnlyByStates: boolean;
  type: detailsDataTypes.MACHINE; // add this field
};

type DetailsData = AbstractData | UserData | MachineData;
function Details(data: DetailsData) {
    switch (data.type) {
        case detailsDataTypes.ABSTRACT:
            data; // data is AbstractData
            break;
            
        case detailsDataTypes.MACHINE:
            data; // data is MachineData
            break;

        case detailsDataTypes.USER:
            data; // data is UserData
            break;

        default:
            data; // data is never (no more possibilities left!)
            break;
    }
}

This technique is called discriminated unions.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda