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

192
Visualizações
Typescript optional property type generic

I would like my function to take any kind of objects but if the objet have a property 'id' making sure that is is either a string or a number.

Here is the minimal example:

interface FnItem {
  id?: string | number;
};

function fn<T extends FnItem>(item: T, callback: (item: T) => void) {
  console.log(item.id);
  callback(item)
};

fn({ name: 'Michel' }, item => item.name);
fn({ name: 'Michel', id: 12 }, item => item.name);

It throws this error

Argument of type '{ name: string; }' is not assignable to parameter of type 'FnItem'.
  Object literal may only specify known properties, and 'name' does not exist in type 'FnItem'
---
Property 'name' does not exist on type 'FnItem
about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

The error is telling you all you need. name doesn't exist on your FnItem type. You can fix it by adding the property or adding an index signature if you want to add arbitrary keys like so:

interface FnItem {
  id?: string | number;
  [key: string]: any; // or whatever types you accept
};

As for the generic, I can't tell what you need it for at the moment, as you could simply define the function as

function fn(item: FnItem): void
about 4 years ago · Juan Pablo Isaza Relatório

0

Assuming that FnItem might be either any object with any properties or any object where id is number|string I would rather stick with this solution:

type FnItem = Record<string, unknown>

type IdValidation<Obj extends Record<string, unknown>> =
    Obj extends { id: infer Id } ? Id extends string | number ? Obj : Obj & { id: never } : Obj;

function fn<T extends FnItem,>(item: IdValidation<T>, callback: (item: IdValidation<T>) => void) {
    console.log(item.id);
    callback(item)
};

fn({ name: 'Michel' }, item => item.name);
fn({ name: 'Michel', id: 12 }, item => item.id);

fn({ name: 'Michel' }, item => item.ya); // error
fn({ name: 'Michel', id: [] }, item => item.id); // id is highlighted as a wrong property

Playground

Since first argument might be any object, we should allow passing Record<string,unknown> which in turn disables our constraint regarding id being number|string. This is why I have added IdValidation utility type. It just checks whether id property meets condition or not. If it meets - leave id as is, otherwise - replace id type with never. Using never allows you to highlight only incorrect property which makes it easy to read and understand.

If you are interested in TS validation techniques you can check my articles here and here

about 4 years ago · Juan Pablo Isaza Relatório

0

If you want to pass a generic then you need to tell the function what concrete type implements your interface:

interface FnItem {
  id?: string | number;
};

function fn<T extends FnItem>(item: T,  callback: (item: T) => void) {
  console.log(item.id);
  callback(item);
};

fn<myType>({ name: 'Michel', id: 12 }, (item:myType)  => { console.log(item.name); });
fn<myType>({ name: 'Michel' }, (item:myType) => { console.log(item.name); });

class myType implements FnItem
{
    name: string = "";
    id?: number;
}

Compiled example

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