dazuaz
dazuaz

Reputation: 23

Using keyof and Pick from only one source list for typings

I want to be able to define the properties I need in only 1 list[], and then use that as the definition for these 2 types I am using, right now I have to individually add them in both places.

Using keyof allows to make sure I am selecting from available props

type DealPropertiesKeys = keyof DealProperties

I can then define what properties should be fetched from the API

  const deal = await hubSpotClient.crm.deals.basicApi.getById(dealId, [
    'dealname',
    'loan_type',
    'asset_type',
    'a_c_square_footage',
    'borrowing_entity_type',
    'borrowing_entity',
    'date_of_formation',
    'estimated_value',
    'exit_strategy',
    'fixed_or_arm',
    'intended_use',
    'lender',
    'loan_channel',
    'loan_program',
    'ltv',
    'project_name',
    'property_address',
    'property_type',
    'requested_terms',
    'subject_property_address',
    'subject_property_city',
    'subject_property_state',
    'subject_property_zip_code',
    'year_built',
    'amount',
    'hubspot_owner_id',
    'outstanding_mortgage_balance',
  ] as DealPropertiesKeys[])

Then when I need to use the returned object, I want to type it based on the selected properties on the request.

type DealProps = Pick<
  DealProperties,
  | 'dealname'
  | 'loan_type'
  | 'asset_type'
  | 'a_c_square_footage'
  | 'borrowing_entity_type'
  | 'borrowing_entity'
  | 'date_of_formation'
  | 'estimated_value'
  | 'exit_strategy'
  | 'fixed_or_arm'
  | 'intended_use'
  | 'lender'
  | 'loan_channel'
  | 'loan_program'
  | 'ltv'
  | 'project_name'
  | 'property_address'
  | 'property_type'
  | 'requested_terms'
  | 'subject_property_address'
  | 'subject_property_city'
  | 'subject_property_state'
  | 'subject_property_zip_code'
  | 'year_built'
  | 'amount'
  | 'hubspot_owner_id'
  | 'outstanding_mortgage_balance'
>

Upvotes: 1

Views: 53

Answers (1)

lepsch
lepsch

Reputation: 10319

The following code should work. The trick is to create first an array as const and then use typeof theArray[number] to get all elements of the array as a union-type. Also, as a const array properties is going to be passed to getById the parameter should be declared readonly (Check the comments in the code).

type DealPropertiesKeys = keyof DealProperties

const requestDealProperties = [
  'dealname',
  'loan_type',
  'asset_type',
  'a_c_square_footage',
  'borrowing_entity_type',
  'borrowing_entity',
  'date_of_formation',
  'estimated_value',
  'exit_strategy',
  'fixed_or_arm',
  'intended_use',
  'lender',
  'loan_channel',
  'loan_program',
  'ltv',
  'project_name',
  'property_address',
  'property_type',
  'requested_terms',
  'subject_property_address',
  'subject_property_city',
  'subject_property_state',
  'subject_property_zip_code',
  'year_built',
  'amount',
  'hubspot_owner_id',
  'outstanding_mortgage_balance',
] as const                          // <- Here - `as const`

// v Here - `typeof theArray[number]`
type RequestDealProperties = typeof requestDealProperties[number]

type DealProps = Pick<
  DealProperties,
  RequestDealProperties            // <- Here
>

// Dummy DealProperties placeholder - it's here just to have the type declaration for the keys
interface DealProperties {
  dealname: string
  loan_type: string
  asset_type: string
  a_c_square_footage: string
  borrowing_entity_type: string
  borrowing_entity: string
  date_of_formation: string
  estimated_value: string
  exit_strategy: string
  fixed_or_arm: string
  intended_use: string
  lender: string
  loan_channel: string
  loan_program: string
  ltv: string
  project_name: string
  property_address: string
  property_type: string
  requested_terms: string
  subject_property_address: string
  subject_property_city: string
  subject_property_state: string
  subject_property_zip_code: string
  year_built: string
  amount: string
  hubspot_owner_id: string
  outstanding_mortgage_balance: string
}


// Test the function
function getById(
  dealId: string,
  properties: readonly DealPropertiesKeys[],  // <- Here - readonly array
) {
  console.log(dealId, properties)
}

getById('1234', requestDealProperties)

Upvotes: 2

Related Questions