typestack / class-transformer

Decorator-based transformation, serialization, and deserialization between objects and classes.
MIT License
6.84k stars 500 forks source link

question: 'T' only refers to a type, but is being used as a value here. #1359

Closed brandonros closed 5 months ago

brandonros commented 2 years ago
class Quote {
  ask_price: string
  ask_size: number
  bid_price: string
  bid_size: number
  last_trade_price: string
  last_extended_hours_trade_price: string
  last_non_reg_trade_price: string
  previous_close: string
  adjusted_previous_close: string
  previous_close_date: string
  symbol: string
  trading_halted: boolean
  has_traded: boolean
  last_trade_price_source: string
  last_non_reg_trade_price_source: string
  updated_at: string
  instrument: string
  instrument_id: string
  state: string
}

const baseRequest = async<T> (token: string, url: string): Promise<T> => {
  console.log({
    message: 'baseRequest',
    url
  })
  assert.ok(token)
  const response = await fetch(url, {
    headers: {
      origin: 'https://robinhood.com',
      authorization: `Bearer ${token}`,
      referer: 'https://robindhood.com',
      'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'
    }
  })
  if (response.status !== 200) {
    throw new Error(`Invalid response status: ${response.status}`)
  }
  const responseBody = await response.json()
  return plainToClass(T, responseBody)
}

const getQuote = (token: string, quoteId: string): Promise<Quote> => {
  return baseRequest<Quote>(token, `https://api.robinhood.com/marketdata/quotes/${quoteId}/?bounds=trading`)
}
brandonros commented 2 years ago

doesn't actually work. curious what I am doing wrong. not telling TypeScript that the T generic is a class?

wpdcastro commented 1 year ago

I'm actually having the same error. Are you resolve this issue?

ElPerenza commented 1 year ago

That's because generics are a Typescript only feature and get stripped at compile time, so you're essentially trying to pass something that doesn't exist to plainToClass.

This is essentially what you're trying to do:

function getResourceById<T>(id: string): T { //the T generic gets stripped at compile time
    //do stuff to get the resource

    return plainToInstance(T, plainObject) //T is not defined
}

getResourceById<Quote>("abc")

What you should be doing is passing the Quote class as a method parameter instead:

function getResourceById<T>(id: string, resourceType: ClassConstructor<T>): T {
    //do stuff to get the resource

    return plainToInstance(resourceType, plainObject)
}

getResourceById("abc", Quote)
diffy0712 commented 5 months ago

Thank you @ElPerenza for your answer. Closing as invalid.

github-actions[bot] commented 4 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.