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

207
Visualizações
Typescript Create a type whose properties are the properties of an interface

I have an interface definition as follows

export interface RoutingMap {
    ticket: {
        id: number
    },
    car: {
        model: string,
        make: number
    }
}

I want to be able to create an interface for an object, which has 2 properties - 1 being a key in the RoutingMap and the other being whatever the type of that Key in the RoutingMap is.

In pseudo-code I image it looking like this

export interface RoutingMessage {
    resource: keyof RoutingMap,
    params: RoutingMap["resource"]
}

The end goal is for me to be able to construct objects like this

const msg: RoutingMessage = {
    resource: "ticket",
    params: { id: 10 }
}

const invalidMsg: RoutingMessage = {
    resource: "something", //TS error - "something" is not a key of routing map
    params: { id: 10 }
}

const invalidMsg2: RoutingMessage = {
    resource: "car"
    params: { model: "tesla", make: true } //TS error - "make" is not a boolean
}

const invalidMsg3: RoutingMessage = {
    resource: "car"
    params: { id: 123 } //TS error - id is not assinable to  {model: string, make: boolean}
}

The RoutingMap is something which would be extended with time, and people should be able to create specific objects, based on the keys (and their values)

As you can see from the pseudo-code example I can set a constraint for the resource, but I need a way to constrain the params property to only allow objects, which match the signature of the Key in the RoutingMap

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

0

Because there are a finite number of keys that match keyof RoutingMap, you can write RoutingMessage as a union of object types where each element of the union corresponds to a particular key, like this:

type RoutingMessage = {
    resource: "ticket";
    params: {
        id: number;
    };
} | {
    resource: "car";
    params: {
        model: string;
        make: number;
    };
}

You can compute RoutingMessage programmatically from RoutingMap by writing it as a "distributive object type" (terminology borrowed from microsoft/TypeScript#47109) where we make a mapped type where each property with key K in RoutingMap is mapped to the desired object type for that key, and then we immediately index into it with keyof RoutingMap, producing the desired union.

type RoutingMessage = { [K in keyof RoutingMap]:
  { resource: K, params: RoutingMap[K] }
}[keyof RoutingMap];

With the above definition, RoutingMessage will gain new union members whenever a new property is added to RoutingMap, as desired.


Let's make sure it behaves how you want:

const msg: RoutingMessage = {
  resource: "ticket",
  params: { id: 10 }
}; // okay

const invalidMsg: RoutingMessage = {
  resource: "something", // error!
  //~~~~~~ <-- Type '"something"' is not assignable to type '"ticket" | "car"'
  params: { id: 10 }
};

const invalidMsg2: RoutingMessage = {
  resource: "car",
  params: { model: "tesla", make: true } // error!
  //  --------------------> ~~~~
  // Type 'boolean' is not assignable to type 'number'.
};

const invalidMsg3: RoutingMessage = {
  resource: "car",
  params: { id: 123 } // error!
  // -----> ~~~~~~~
  // Type '{ id: number; }' is not assignable to type '{ model: string; make: number; }' 
};

Looks good!

Playground link to code

about 4 years ago · Juan Pablo Isaza Relatório

0

export interface RoutingMessage {
    resource: keyof RoutingMap,
    params: RoutingMap[this["resource"]]
}
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