typescripthubspot

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'
>

Solution

  • 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)