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

130
Visualizações
How can I implement custom class with overridable list type?

I have a Nextjs project using next v10.1.2 and Typescript v4.4.4 I would like to have a class SortableList that encapsulates a list of a custom type. The only requirement is that the list extends my abstract class OrderedItem.

Currently, I am getting an error when I try to access a property on a class that extends OrderedItem from a new SortableList object.

Is this possible in Typescript and what is the correct way to set this up?

Code:

OrderedItem.ts

// The purpose of this class is to ensure that items in a list can be ordered.
abstract class OrderedItem {
  order: number

  constructor(order: number) {
    this.order = order
  }
}

export default OrderedItem

CustomListItem.ts

import OrderedItem from './OrderedItem'

// This is an example of a class that I would like to be orderable.
class CustomListItem extends OrderedItem {
  name: string
  jsx: JSX.Element

  constructor(order: number, name: string, jsx: JSX.Element) {
    super(order)
    this.name = name
    this.jsx = jsx
  }
}

export default CustomListItem

SortableList.ts

import OrderedItem from './OrderedItem'

class SortableList {
  // I want this array to be overridden by a custom class like CustomListItem
  list: OrderedItem[]

  constructor(list: OrderedItem[]) {
    this.list = list
  }

  sortByOrder = (): void => {
    this.list = this.list.sort((a, b) => a.order - b.order)
  }

  sortByReverseOrder = (): void => {
    this.list = this.list.sort((a, b) => b.order - a.order)
  }
}

export default SortableList

example.tsx

import CustomListItem from './CustomListItem'
import SortableList from './SortableList'

export default function Example() {
  const customList: CustomListItem[] = [
    new CustomListItem(3, 'name3', <div></div>),
    new CustomListItem(1, 'name1', <div></div>),
    new CustomListItem(2, 'name2', <div></div>),
  ]
  const sortableList: SortableList = new SortableList(customList)
  sortableList.sortByOrder()

  return sortableList.list.map(item => item.jsx)
}

The error I am getting from this example is in the return statement of example.tsx when trying to access the jsx property on item since item is typed as OrderedItem and not CustomListItem.

Error: Property 'jsx' does not exist on type 'OrderedItem'.

What is the correct way to do this? I tried messing around with declaring SortableList with <T> and initializing it like

const sortableList = new SortableList<CustomListItem>(customList), but I'm not familiar with how that is supposed to work.

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

0

The problem is when you access an element of your SortableList the compiler knows just that it is an OrderedItem which has no property jsx.

There are two main solutions to this:

  1. You know that your item will be always of a certain type (like in your case) and you cast it to that type. Easy to implement, but I really warn you that this is not a good idea, because you are going to break object programming principles and also this can lead to runtime errors which are very hard to debug, for example you put an item which is not of CustomListItem in the list and has no property jsx. This is how it is done:
sortableList.list.map(item => (item as CustomListItem).jsx)
  1. The formal way is to use generics. A generics is just a placeholder for a type in your code, when you use it, it will be replaced by the specified type. In your case you need furthermore a constraint on that generic which force the implementation specified type to extends your OrderedItem class. In this way there are no pratical cases where you will get an unexpected error, because the ts compiler prevent them by checking your types. This is how it is done in your case:

SortableList.ts

import OrderedItem from './OrderedItem'

// T is the generic
// T extends OrderedItem is the constraint
class SortableList<T extends OrderedItem> {
  // this array can contains only elements
  // that are descendant of T
  // T is always a descendant of OrderedItem
  list: T[]

  constructor(list: T[]) {
    this.list = list
  }

  sortByOrder = (): void => {
    this.list = this.list.sort((a, b) => a.order - b.order)
  }

  sortByReverseOrder = (): void => {
    this.list = this.list.sort((a, b) => b.order - a.order)
  }
}

export default SortableList

example.tsx

import CustomListItem from './CustomListItem'
import SortableList from './SortableList'

export default function Example() {
  const customList: CustomListItem[] = [
    new CustomListItem(3, 'name3', <div></div>),
    new CustomListItem(1, 'name1', <div></div>),
    new CustomListItem(2, 'name2', <div></div>),
  ]
  const sortableList: SortableList<CustomListItem> =
         new SortableList<CustomListItem>(customList)
  sortableList.sortByOrder()

  return sortableList.list.map(item => item.jsx)
}
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